(idToken string)
| 108 | } |
| 109 | |
| 110 | func (p *Apple) parseAndVerifyIdToken(idToken string) (jwt.MapClaims, error) { |
| 111 | if idToken == "" { |
| 112 | return nil, errors.New("empty id_token") |
| 113 | } |
| 114 | |
| 115 | // extract the token claims |
| 116 | // --- |
| 117 | claims := jwt.MapClaims{} |
| 118 | _, _, err := jwt.NewParser().ParseUnverified(idToken, claims) |
| 119 | if err != nil { |
| 120 | return nil, err |
| 121 | } |
| 122 | |
| 123 | // validate common claims per https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/verifying_a_user#3383769 |
| 124 | // --- |
| 125 | jwtValidator := jwt.NewValidator( |
| 126 | jwt.WithExpirationRequired(), |
| 127 | jwt.WithIssuedAt(), |
| 128 | jwt.WithLeeway(idTokenLeeway), |
| 129 | jwt.WithIssuer("https://appleid.apple.com"), |
| 130 | jwt.WithAudience(p.clientId), |
| 131 | ) |
| 132 | err = jwtValidator.Validate(claims) |
| 133 | if err != nil { |
| 134 | return nil, err |
| 135 | } |
| 136 | |
| 137 | // validate id_token signature |
| 138 | // |
| 139 | // note: this step could be technically considered optional because we trust |
| 140 | // the token which is a result of direct TLS communication with the provider |
| 141 | // (see also https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation) |
| 142 | // --- |
| 143 | err = jwk.ValidateTokenSignature(p.ctx, idToken, p.jwksURL) |
| 144 | if err != nil { |
| 145 | return nil, fmt.Errorf("id_token validation failed: %w", err) |
| 146 | } |
| 147 | |
| 148 | return claims, nil |
| 149 | } |
no test coverage detected