(ctx context.Context, c *Client)
| 52 | } |
| 53 | |
| 54 | func (v *Validator) Validate(ctx context.Context, c *Client) error { |
| 55 | if c.TokenEndpointAuthMethod == "" { |
| 56 | c.TokenEndpointAuthMethod = "client_secret_basic" |
| 57 | } else if c.TokenEndpointAuthMethod == "private_key_jwt" { |
| 58 | if len(c.JSONWebKeysURI) == 0 && c.GetJSONWebKeys() == nil { |
| 59 | return errors.WithStack(ErrInvalidClientMetadata.WithHint("When token_endpoint_auth_method is 'private_key_jwt', either jwks or jwks_uri must be set.")) |
| 60 | } |
| 61 | if c.TokenEndpointAuthSigningAlgorithm != "" && !isSupportedAuthTokenSigningAlg(c.TokenEndpointAuthSigningAlgorithm) { |
| 62 | return errors.WithStack(ErrInvalidClientMetadata.WithHint("Only RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384 and ES512 are supported as algorithms for private key authentication.")) |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | if len(c.JSONWebKeysURI) > 0 && c.GetJSONWebKeys() != nil { |
| 67 | return errors.WithStack(ErrInvalidClientMetadata.WithHint("Fields jwks and jwks_uri can not both be set, you must choose one.")) |
| 68 | } |
| 69 | |
| 70 | if jsonWebKeys := c.GetJSONWebKeys(); jsonWebKeys != nil { |
| 71 | for _, k := range jsonWebKeys.Keys { |
| 72 | if !k.Valid() { |
| 73 | return errors.WithStack(ErrInvalidClientMetadata.WithHint("Invalid JSON web key in set.")) |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | if v.r.Config().ClientHTTPNoPrivateIPRanges() { |
| 79 | values := map[string]string{ |
| 80 | "jwks_uri": c.JSONWebKeysURI, |
| 81 | "backchannel_logout_uri": c.BackChannelLogoutURI, |
| 82 | } |
| 83 | |
| 84 | for k, v := range c.RequestURIs { |
| 85 | values[fmt.Sprintf("request_uris.%d", k)] = v |
| 86 | } |
| 87 | |
| 88 | if err := ipx.AreAllAssociatedIPsAllowed(values); err != nil { |
| 89 | return errors.WithStack(ErrInvalidClientMetadata.WithHintf("Client IP address is not allowed: %s", err)) |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | // TODO: For clients that support dynamic registration, validate that each of these URIs are part of the redirect_uris, as per the spec. |
| 94 | // The authorization server SHOULD check to see if the "logo_uri", "tos_uri", "client_uri", and "policy_uri" have the same host and scheme as the those defined in the array of "redirect_uris" and that all of these URIs resolve to valid web pages. |
| 95 | // https://datatracker.ietf.org/doc/html/rfc7591#section-5 |
| 96 | |
| 97 | // TODO: In addition, the logo_uri should be a valid image. |
| 98 | // The value of this field MUST point to a valid image file. |
| 99 | |
| 100 | for f, uri := range map[string]string{ |
| 101 | "tos_uri": c.TermsOfServiceURI, |
| 102 | "policy_uri": c.PolicyURI, |
| 103 | "logo_uri": c.LogoURI, |
| 104 | "client_uri": c.ClientURI, |
| 105 | } { |
| 106 | if uri == "" { |
| 107 | continue |
| 108 | } |
| 109 | u, err := url.ParseRequestURI(uri) |
| 110 | if err != nil { |
| 111 | return errors.WithStack(ErrInvalidClientMetadata.WithHintf("Field %s must be a valid URI.", f)) |
no test coverage detected