Parse the token and return the type of token. At the moment in Chainloop we have 3 types of tokens: 1. User account token 2. API token 3. Federated token Each one of them have an associated audience claim that we use to identify the type of token. If the token is not present, nor we cannot match it
(token string)
| 45 | // Each one of them have an associated audience claim that we use to identify the type of token. If the token is not |
| 46 | // present, nor we cannot match it with one of the expected audience, return nil. |
| 47 | func Parse(token string) (*ParsedToken, error) { |
| 48 | if token == "" { |
| 49 | return nil, nil |
| 50 | } |
| 51 | |
| 52 | // Create a parser without claims validation |
| 53 | parser := jwt.NewParser(jwt.WithoutClaimsValidation()) |
| 54 | |
| 55 | // Parse the token without verification |
| 56 | t, _, err := parser.ParseUnverified(token, jwt.MapClaims{}) |
| 57 | if err != nil { |
| 58 | return nil, err |
| 59 | } |
| 60 | |
| 61 | // Extract generic claims otherwise, we would have to parse |
| 62 | // the token again to get the claims for each type |
| 63 | claims, ok := t.Claims.(jwt.MapClaims) |
| 64 | if !ok { |
| 65 | return nil, nil |
| 66 | } |
| 67 | |
| 68 | // Supports both string and array formats per JWT RFC 7519 |
| 69 | // Takes first array element when multiple audiences exist |
| 70 | var audience string |
| 71 | switch aud := claims["aud"].(type) { |
| 72 | case string: |
| 73 | audience = aud |
| 74 | case []interface{}: |
| 75 | if len(aud) > 0 { |
| 76 | audience, _ = aud[0].(string) |
| 77 | } |
| 78 | default: |
| 79 | return nil, nil |
| 80 | } |
| 81 | |
| 82 | if audience == "" { |
| 83 | return nil, nil |
| 84 | } |
| 85 | |
| 86 | pToken := &ParsedToken{} |
| 87 | |
| 88 | // Determines token type and id based on audience: |
| 89 | // 1. API Tokens: |
| 90 | // - Type: AUTH_TYPE_API_TOKEN |
| 91 | // - ID: 'jti' claim (JWT ID) |
| 92 | // - OrgID: 'org_id' claim |
| 93 | // 2. User Tokens: |
| 94 | // - Type: AUTH_TYPE_USER |
| 95 | // - ID: 'user_id' claim |
| 96 | // 3. Federated Tokens: |
| 97 | // - Type: AUTH_TYPE_FEDERATED |
| 98 | // - ID: 'iss' claim (issuer URL) |
| 99 | switch audience { |
| 100 | case apiTokenAudience: |
| 101 | pToken.TokenType = v1.Attestation_Auth_AUTH_TYPE_API_TOKEN |
| 102 | if tokenID, ok := claims["jti"].(string); ok { |
| 103 | pToken.ID = tokenID |
| 104 | } |
no outgoing calls