Skip to content

'aud' claim is not necessarily a string #114

@pedromss

Description

@pedromss

Hi. Was wiring things up in a service and noticed that jwt.StandardClaims assumes aud is a string.

According to the RFC https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 this field can sometimes be a string. The way its written leads me to believe a []string is actually more common, but that's interpretation.

The quick way I found around this was to use jwt.MapClaims and serialize + deserialize this into a custom struct. Could this be improved by transforming aud into a interface{} and having a method on jwt.StandardClaims like:

type St struct {
	Aud interface{} `json:"aud"`
}

func (sc St) Audience() ([]string, error) {
  if v, ok := sc.Aud.(string); ok {
  	return []string{v}, nil
  } else if v, ok := sc.Aud.([]interface{}); ok {
  	var results []string
	  for _, s := range v {
	  	if asString, isString := s.(string); isString {
			results = append(results, asString)
		} else {
			return nil, e.New("found an aud that is not a string")
		}
	  }
  	return results, nil
  }

  return nil, e.New("unparsable aud claim")
}

Simple tests to verify it works at some level at least:

func TestBla(t *testing.T) {
	var singleAud St
	err := json.Unmarshal([]byte(`{ "aud": "bla" }`), &singleAud)
	require.NoError(t, err)
	audience, err := singleAud.Audience()
	require.NoError(t, err)
	require.ElementsMatch(t, audience, []string{"bla"})

	var multiAud St
	err = json.Unmarshal([]byte(`{ "aud": [ "bla", "ble" ] }`), &multiAud)
	require.NoError(t, err)
	audience, err = multiAud.Audience()
	require.NoError(t, err)
	require.ElementsMatch(t, audience, []string{"bla", "ble"})
}

If aud is the only parameter that can be either a string or a []string adding a new type might be a more pleasant experience:

type StandardClaimsWithSingleAud struct {
  Aud string ...
}

type StandardClaimsWithMulitAud struct {
  Aud []string ...
}

Is there already a way to deal with this in a typed fashion instead of dealing with the untyped jwt.MapClaims?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions