in auth/token_verifier.go [250:308]
func (tv *tokenVerifier) verifyHeaderAndBody(token string, isEmulator bool) (*Token, error) {
var (
header jwtHeader
payload Token
)
segments := strings.Split(token, ".")
if len(segments) != 3 {
return nil, errors.New("incorrect number of segments")
}
if err := decode(segments[0], &header); err != nil {
return nil, err
}
if err := decode(segments[1], &payload); err != nil {
return nil, err
}
issuer := tv.issuerPrefix + tv.projectID
if !isEmulator && header.KeyID == "" {
if payload.Audience == firebaseAudience {
return nil, fmt.Errorf("expected %s but got a custom token", tv.articledShortName)
}
return nil, fmt.Errorf("%s has no 'kid' header", tv.shortName)
}
if !isEmulator && header.Algorithm != "RS256" {
return nil, fmt.Errorf("%s has invalid algorithm; expected 'RS256' but got %q",
tv.shortName, header.Algorithm)
}
if payload.Audience != tv.projectID {
return nil, fmt.Errorf("%s has invalid 'aud' (audience) claim; expected %q but got %q; %s",
tv.shortName, tv.projectID, payload.Audience, tv.getProjectIDMatchMessage())
}
if payload.Issuer != issuer {
return nil, fmt.Errorf("%s has invalid 'iss' (issuer) claim; expected %q but got %q; %s",
tv.shortName, issuer, payload.Issuer, tv.getProjectIDMatchMessage())
}
if payload.Subject == "" {
return nil, fmt.Errorf("%s has empty 'sub' (subject) claim", tv.shortName)
}
if len(payload.Subject) > 128 {
return nil, fmt.Errorf("%s has a 'sub' (subject) claim longer than 128 characters",
tv.shortName)
}
payload.UID = payload.Subject
var customClaims map[string]interface{}
if err := decode(segments[1], &customClaims); err != nil {
return nil, err
}
for _, standardClaim := range []string{"iss", "aud", "exp", "iat", "sub", "uid"} {
delete(customClaims, standardClaim)
}
payload.Claims = customClaims
return &payload, nil
}