package jwt import ( "context" "github.com/pkg/errors" ) // Parse an access token and return a struct with all the claims. Does validation on // all the claims, including checking if it is expired, has a valid issuer, and // has the correct scope. func (gen *TokenGenerator) ValidateAccess( ctx context.Context, tokenString string, ) (*AccessToken, error) { if tokenString == "" { return nil, errors.New("Access token string not provided") } claims, err := parseToken(gen.secretKey, tokenString) if err != nil { return nil, errors.Wrap(err, "parseToken") } expiry, err := checkTokenExpired(claims["exp"]) if err != nil { return nil, errors.Wrap(err, "checkTokenExpired") } issuer, err := checkTokenIssuer(gen.trustedHost, claims["iss"]) if err != nil { return nil, errors.Wrap(err, "checkTokenIssuer") } ttl, err := getTokenTTL(claims["ttl"]) if err != nil { return nil, errors.Wrap(err, "getTokenTTL") } scope, err := getTokenScope(claims["scope"]) if err != nil { return nil, errors.Wrap(err, "getTokenScope") } if scope != "access" { return nil, errors.New("Token is not an Access token") } issuedAt, err := getIssuedTime(claims["iat"]) if err != nil { return nil, errors.Wrap(err, "getIssuedTime") } subject, err := getTokenSubject(claims["sub"]) if err != nil { return nil, errors.Wrap(err, "getTokenSubject") } fresh, err := getFreshTime(claims["fresh"]) if err != nil { return nil, errors.Wrap(err, "getFreshTime") } jti, err := getTokenJTI(claims["jti"]) if err != nil { return nil, errors.Wrap(err, "getTokenJTI") } token := &AccessToken{ ISS: issuer, TTL: ttl, EXP: expiry, IAT: issuedAt, SUB: subject, Fresh: fresh, JTI: jti, Scope: scope, db: gen.dbConn, } valid, err := token.CheckNotRevoked(ctx) if err != nil && gen.dbConn != nil { return nil, errors.Wrap(err, "token.CheckNotRevoked") } if !valid && gen.dbConn != nil { return nil, errors.New("Token has been revoked") } return token, nil } // Parse a refresh token and return a struct with all the claims. Does validation on // all the claims, including checking if it is expired, has a valid issuer, and // has the correct scope. func (gen *TokenGenerator) ValidateRefresh( ctx context.Context, tokenString string, ) (*RefreshToken, error) { if tokenString == "" { return nil, errors.New("Refresh token string not provided") } claims, err := parseToken(gen.secretKey, tokenString) if err != nil { return nil, errors.Wrap(err, "parseToken") } expiry, err := checkTokenExpired(claims["exp"]) if err != nil { return nil, errors.Wrap(err, "checkTokenExpired") } issuer, err := checkTokenIssuer(gen.trustedHost, claims["iss"]) if err != nil { return nil, errors.Wrap(err, "checkTokenIssuer") } ttl, err := getTokenTTL(claims["ttl"]) if err != nil { return nil, errors.Wrap(err, "getTokenTTL") } scope, err := getTokenScope(claims["scope"]) if err != nil { return nil, errors.Wrap(err, "getTokenScope") } if scope != "refresh" { return nil, errors.New("Token is not an Refresh token") } issuedAt, err := getIssuedTime(claims["iat"]) if err != nil { return nil, errors.Wrap(err, "getIssuedTime") } subject, err := getTokenSubject(claims["sub"]) if err != nil { return nil, errors.Wrap(err, "getTokenSubject") } jti, err := getTokenJTI(claims["jti"]) if err != nil { return nil, errors.Wrap(err, "getTokenJTI") } token := &RefreshToken{ ISS: issuer, TTL: ttl, EXP: expiry, IAT: issuedAt, SUB: subject, JTI: jti, Scope: scope, db: gen.dbConn, } valid, err := token.CheckNotRevoked(ctx) if err != nil && gen.dbConn != nil { return nil, errors.Wrap(err, "token.CheckNotRevoked") } if !valid && gen.dbConn != nil { return nil, errors.New("Token has been revoked") } return token, nil }