Description

I can't get information from the client certificate such as Organization and CommonName

How to reproduce

package main

import (
    "fmt"
    "net/http"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func Ping(c *gin.Context) {
    cert := c.Request.TLS.PeerCertificates // Returns an empty array
    fmt.Println(cert)
    c.JSON(http.StatusOK, gin.H{"payload": "Hello!"})
}

func main() {
    gin.SetMode(gin.ReleaseMode)
    r := gin.Default()
    r.Use(cors.Default())
    r.GET("/ping", Ping)
    r.RunTLS("0.0.0.0:8188", "cert.pem", "key.pem")
}

Expectations

An array with my certificates should be printed

Actual result

En empty array is printed

Environment

  • go version: go version go1.17.8 windows/amd64

Comment From: mohsalsaleem

If you read through the docs at https://pkg.go.dev/crypto/tls?utm_source=gopls#ConnectionState.PeerCertificates, it says

PeerCertificates are the parsed certificates sent by the peer, in the order in which they were sent... On the client side, it can't be empty. On the server side, it can be empty if Config.ClientAuth is not RequireAnyClientCert or RequireAndVerifyClientCert.

This means that, the Config.ClientAuth must be set to either of the mentioned values and the client must send the certs.

Below is a working example I've attached.

I've used mkcert to generate the cert and key.

mkcert 127.0.0.1

main.go

package main

import (
    "crypto/tls"
    "fmt"
    "net/http"

    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"
)

func Ping(c *gin.Context) {
    certs := c.Request.TLS.PeerCertificates 
    for _, v := range certs {
        fmt.Printf("v.Issuer: %v\n", v.Issuer)
    }
    c.JSON(http.StatusOK, gin.H{"payload": "Hello!"})
}

func main() {
    gin.SetMode(gin.ReleaseMode)
    r := gin.Default()
    r.Use(cors.Default())
    r.GET("/ping", Ping)
    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAnyClientCert,
    }

    s := http.Server{
        Addr:      "127.0.0.1:8188",
        Handler:   r,
        TLSConfig: tlsConfig,
    }
    s.ListenAndServeTLS("127.0.0.1.pem", "127.0.0.1-key.pem")
}

cURL command

curl -v \
--key 127.0.0.1-key.pem \
--cert 127.0.0.1.pem \
 https://127.0.0.1:8188/ping

Output

v.Issuer: CN=mkcert user@user-LT.laptop.local (user),OU=user@user-LT.laptop.local (user),O=mkcert development CA
v.Issuer: CN=mkcert user@user-LT.laptop.local (user),OU=user@user-LT.laptop.local (user),O=mkcert development CA
[GIN] 2022/04/01 - 11:27:36 | 200 |      94.016µs |       127.0.0.1 | GET      "/ping"