Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/jwt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func signToken() error {
// add command line claims
if len(flagClaims) > 0 {
for k, v := range flagClaims {
claims[k] = v
claims[jwt.MapClaimsKey(k)] = v
}
}

Expand Down
47 changes: 35 additions & 12 deletions map_claims.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,67 @@ import (
"fmt"
)

// MapClaims is a claims type that uses the map[string]any for JSON
// decoding. This is the default claims type if you don't supply one
type MapClaims map[string]any
// MapClaimsKey is a type alias for claim keys in the [MapClaims] type.
type MapClaimsKey string

var (
// Exp is the "exp" claim key according to RFC 7519 section 4.1.4.
Exp MapClaimsKey = "exp"

// Nbf is the "nbf" claim key according to RFC 7519 section 4.1.5.
Nbf MapClaimsKey = "nbf"

// Iat is the "iat" claim key according to RFC 7519 section 4.1.6.
Iat MapClaimsKey = "iat"

// Aud is the "aud" claim key according to RFC 7519 section 4.1.3.
Aud MapClaimsKey = "aud"

// Iss is the "iss" claim key according to RFC 7519 section 4.1.1.
Iss MapClaimsKey = "iss"

// Sub is the "sub" claim key according to RFC 7519 section 4.1.2.
Sub MapClaimsKey = "sub"
)

// MapClaims is a claims type that uses of map of [MapClaimsKey] with value [any]
// for JSON decoding. This is the default claims type if you do not supply one.
type MapClaims map[MapClaimsKey]any

// GetExpirationTime implements the Claims interface.
func (m MapClaims) GetExpirationTime() (*NumericDate, error) {
return m.parseNumericDate("exp")
return m.parseNumericDate(Exp)
}

// GetNotBefore implements the Claims interface.
func (m MapClaims) GetNotBefore() (*NumericDate, error) {
return m.parseNumericDate("nbf")
return m.parseNumericDate(Nbf)
}

// GetIssuedAt implements the Claims interface.
func (m MapClaims) GetIssuedAt() (*NumericDate, error) {
return m.parseNumericDate("iat")
return m.parseNumericDate(Iat)
}

// GetAudience implements the Claims interface.
func (m MapClaims) GetAudience() (ClaimStrings, error) {
return m.parseClaimsString("aud")
return m.parseClaimsString(Aud)
}

// GetIssuer implements the Claims interface.
func (m MapClaims) GetIssuer() (string, error) {
return m.parseString("iss")
return m.parseString(Iss)
}

// GetSubject implements the Claims interface.
func (m MapClaims) GetSubject() (string, error) {
return m.parseString("sub")
return m.parseString(Sub)
}

// parseNumericDate tries to parse a key in the map claims type as a number
// date. This will succeed, if the underlying type is either a [float64] or a
// [json.Number]. Otherwise, nil will be returned.
func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) {
func (m MapClaims) parseNumericDate(key MapClaimsKey) (*NumericDate, error) {
v, ok := m[key]
if !ok {
return nil, nil
Expand All @@ -66,7 +89,7 @@ func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) {

// parseClaimsString tries to parse a key in the map claims type as a
// [ClaimsStrings] type, which can either be a string or an array of string.
func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) {
func (m MapClaims) parseClaimsString(key MapClaimsKey) (ClaimStrings, error) {
var cs []string
switch v := m[key].(type) {
case string:
Expand All @@ -89,7 +112,7 @@ func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) {
// parseString tries to parse a key in the map claims type as a [string] type.
// If the key does not exist, an empty string is returned. If the key has the
// wrong type, an error is returned.
func (m MapClaims) parseString(key string) (string, error) {
func (m MapClaims) parseString(key MapClaimsKey) (string, error) {
var (
ok bool
raw any
Expand Down
36 changes: 36 additions & 0 deletions map_claims_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package jwt_test

import (
"fmt"

"github.com/golang-jwt/jwt/v5"
)

var (
// OpenIdConnectEMail represents the "email" claim as defined in
// OpenID Connect Core 1.0, section 5.1.
//
// Reference: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
OpenIdConnectEMail jwt.MapClaimsKey = "email"
)

// ExampleMapClaims shows how to create a token with custom claims using
// [jwt.MapClaims] and the custom [jwt.MapClaimsKey].
func ExampleMapClaims() {
claims := jwt.MapClaims{
"custom_claim": "custom_value",
OpenIdConnectEMail: "me@example.com",
jwt.Sub: "me",
}

t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
s, err := t.SignedString([]byte("secret"))
if err != nil {
panic(err)
}

fmt.Println(s)

// Output:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21fY2xhaW0iOiJjdXN0b21fdmFsdWUiLCJlbWFpbCI6Im1lQGV4YW1wbGUuY29tIiwic3ViIjoibWUifQ.ylWqOBiOzsJpcJQarXmPtvgGMP9d72Zc2GtEdriqXko
}
2 changes: 1 addition & 1 deletion map_claims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestMapClaimsVerifyExpiresAtExpire(t *testing.T) {

func TestMapClaims_parseString(t *testing.T) {
type args struct {
key string
key MapClaimsKey
}
tests := []struct {
name string
Expand Down