Spaces:
Paused
Paused
| from authlib.oauth2.rfc8414 import AuthorizationServerMetadata | |
| from authlib.oauth2.rfc8414.models import validate_array_value | |
| class OpenIDProviderMetadata(AuthorizationServerMetadata): | |
| REGISTRY_KEYS = [ | |
| 'issuer', 'authorization_endpoint', 'token_endpoint', | |
| 'jwks_uri', 'registration_endpoint', 'scopes_supported', | |
| 'response_types_supported', 'response_modes_supported', | |
| 'grant_types_supported', | |
| 'token_endpoint_auth_methods_supported', | |
| 'token_endpoint_auth_signing_alg_values_supported', | |
| 'service_documentation', 'ui_locales_supported', | |
| 'op_policy_uri', 'op_tos_uri', | |
| # added by OpenID | |
| 'acr_values_supported', 'subject_types_supported', | |
| 'id_token_signing_alg_values_supported', | |
| 'id_token_encryption_alg_values_supported', | |
| 'id_token_encryption_enc_values_supported', | |
| 'userinfo_signing_alg_values_supported', | |
| 'userinfo_encryption_alg_values_supported', | |
| 'userinfo_encryption_enc_values_supported', | |
| 'request_object_signing_alg_values_supported', | |
| 'request_object_encryption_alg_values_supported', | |
| 'request_object_encryption_enc_values_supported', | |
| 'display_values_supported', | |
| 'claim_types_supported', | |
| 'claims_supported', | |
| 'claims_locales_supported', | |
| 'claims_parameter_supported', | |
| 'request_parameter_supported', | |
| 'request_uri_parameter_supported', | |
| 'require_request_uri_registration', | |
| # not defined by OpenID | |
| # 'revocation_endpoint', | |
| # 'revocation_endpoint_auth_methods_supported', | |
| # 'revocation_endpoint_auth_signing_alg_values_supported', | |
| # 'introspection_endpoint', | |
| # 'introspection_endpoint_auth_methods_supported', | |
| # 'introspection_endpoint_auth_signing_alg_values_supported', | |
| # 'code_challenge_methods_supported', | |
| ] | |
| def validate_jwks_uri(self): | |
| # REQUIRED in OpenID Connect | |
| jwks_uri = self.get('jwks_uri') | |
| if jwks_uri is None: | |
| raise ValueError('"jwks_uri" is required') | |
| return super().validate_jwks_uri() | |
| def validate_acr_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the Authentication | |
| Context Class References that this OP supports. | |
| """ | |
| validate_array_value(self, 'acr_values_supported') | |
| def validate_subject_types_supported(self): | |
| """REQUIRED. JSON array containing a list of the Subject Identifier | |
| types that this OP supports. Valid types include pairwise and public. | |
| """ | |
| # 1. REQUIRED | |
| values = self.get('subject_types_supported') | |
| if values is None: | |
| raise ValueError('"subject_types_supported" is required') | |
| # 2. JSON array | |
| if not isinstance(values, list): | |
| raise ValueError('"subject_types_supported" MUST be JSON array') | |
| # 3. Valid types include pairwise and public | |
| valid_types = {'pairwise', 'public'} | |
| if not valid_types.issuperset(set(values)): | |
| raise ValueError( | |
| '"subject_types_supported" contains invalid values') | |
| def validate_id_token_signing_alg_values_supported(self): | |
| """REQUIRED. JSON array containing a list of the JWS signing | |
| algorithms (alg values) supported by the OP for the ID Token to | |
| encode the Claims in a JWT [JWT]. The algorithm RS256 MUST be | |
| included. The value none MAY be supported, but MUST NOT be used | |
| unless the Response Type used returns no ID Token from the | |
| Authorization Endpoint (such as when using the Authorization | |
| Code Flow). | |
| """ | |
| # 1. REQUIRED | |
| values = self.get('id_token_signing_alg_values_supported') | |
| if values is None: | |
| raise ValueError('"id_token_signing_alg_values_supported" is required') | |
| # 2. JSON array | |
| if not isinstance(values, list): | |
| raise ValueError('"id_token_signing_alg_values_supported" MUST be JSON array') | |
| # 3. The algorithm RS256 MUST be included | |
| if 'RS256' not in values: | |
| raise ValueError( | |
| '"RS256" MUST be included in "id_token_signing_alg_values_supported"') | |
| def validate_id_token_encryption_alg_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (alg values) supported by the OP for the ID Token to | |
| encode the Claims in a JWT. | |
| """ | |
| validate_array_value(self, 'id_token_encryption_alg_values_supported') | |
| def validate_id_token_encryption_enc_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (enc values) supported by the OP for the ID Token to | |
| encode the Claims in a JWT. | |
| """ | |
| validate_array_value(self, 'id_token_encryption_enc_values_supported') | |
| def validate_userinfo_signing_alg_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWS signing | |
| algorithms (alg values) [JWA] supported by the UserInfo Endpoint | |
| to encode the Claims in a JWT. The value none MAY be included. | |
| """ | |
| validate_array_value(self, 'userinfo_signing_alg_values_supported') | |
| def validate_userinfo_encryption_alg_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (alg values) [JWA] supported by the UserInfo Endpoint | |
| to encode the Claims in a JWT. | |
| """ | |
| validate_array_value(self, 'userinfo_encryption_alg_values_supported') | |
| def validate_userinfo_encryption_enc_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (enc values) [JWA] supported by the UserInfo Endpoint | |
| to encode the Claims in a JWT. | |
| """ | |
| validate_array_value(self, 'userinfo_encryption_enc_values_supported') | |
| def validate_request_object_signing_alg_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWS signing | |
| algorithms (alg values) supported by the OP for Request Objects, | |
| which are described in Section 6.1 of OpenID Connect Core 1.0. | |
| These algorithms are used both when the Request Object is passed | |
| by value (using the request parameter) and when it is passed by | |
| reference (using the request_uri parameter). Servers SHOULD support | |
| none and RS256. | |
| """ | |
| values = self.get('request_object_signing_alg_values_supported') | |
| if not values: | |
| return | |
| if not isinstance(values, list): | |
| raise ValueError('"request_object_signing_alg_values_supported" MUST be JSON array') | |
| # Servers SHOULD support none and RS256 | |
| if 'none' not in values or 'RS256' not in values: | |
| raise ValueError( | |
| '"request_object_signing_alg_values_supported" ' | |
| 'SHOULD support none and RS256') | |
| def validate_request_object_encryption_alg_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (alg values) supported by the OP for Request Objects. | |
| These algorithms are used both when the Request Object is passed | |
| by value and when it is passed by reference. | |
| """ | |
| validate_array_value(self, 'request_object_encryption_alg_values_supported') | |
| def validate_request_object_encryption_enc_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the JWE encryption | |
| algorithms (enc values) supported by the OP for Request Objects. | |
| These algorithms are used both when the Request Object is passed | |
| by value and when it is passed by reference. | |
| """ | |
| validate_array_value(self, 'request_object_encryption_enc_values_supported') | |
| def validate_display_values_supported(self): | |
| """OPTIONAL. JSON array containing a list of the display parameter | |
| values that the OpenID Provider supports. These values are described | |
| in Section 3.1.2.1 of OpenID Connect Core 1.0. | |
| """ | |
| values = self.get('display_values_supported') | |
| if not values: | |
| return | |
| if not isinstance(values, list): | |
| raise ValueError('"display_values_supported" MUST be JSON array') | |
| valid_values = {'page', 'popup', 'touch', 'wap'} | |
| if not valid_values.issuperset(set(values)): | |
| raise ValueError('"display_values_supported" contains invalid values') | |
| def validate_claim_types_supported(self): | |
| """OPTIONAL. JSON array containing a list of the Claim Types that | |
| the OpenID Provider supports. These Claim Types are described in | |
| Section 5.6 of OpenID Connect Core 1.0. Values defined by this | |
| specification are normal, aggregated, and distributed. If omitted, | |
| the implementation supports only normal Claims. | |
| """ | |
| values = self.get('claim_types_supported') | |
| if not values: | |
| return | |
| if not isinstance(values, list): | |
| raise ValueError('"claim_types_supported" MUST be JSON array') | |
| valid_values = {'normal', 'aggregated', 'distributed'} | |
| if not valid_values.issuperset(set(values)): | |
| raise ValueError('"claim_types_supported" contains invalid values') | |
| def validate_claims_supported(self): | |
| """RECOMMENDED. JSON array containing a list of the Claim Names | |
| of the Claims that the OpenID Provider MAY be able to supply values | |
| for. Note that for privacy or other reasons, this might not be an | |
| exhaustive list. | |
| """ | |
| validate_array_value(self, 'claims_supported') | |
| def validate_claims_locales_supported(self): | |
| """OPTIONAL. Languages and scripts supported for values in Claims | |
| being returned, represented as a JSON array of BCP47 [RFC5646] | |
| language tag values. Not all languages and scripts are necessarily | |
| supported for all Claim values. | |
| """ | |
| validate_array_value(self, 'claims_locales_supported') | |
| def validate_claims_parameter_supported(self): | |
| """OPTIONAL. Boolean value specifying whether the OP supports use of | |
| the claims parameter, with true indicating support. If omitted, the | |
| default value is false. | |
| """ | |
| _validate_boolean_value(self, 'claims_parameter_supported') | |
| def validate_request_parameter_supported(self): | |
| """OPTIONAL. Boolean value specifying whether the OP supports use of | |
| the request parameter, with true indicating support. If omitted, the | |
| default value is false. | |
| """ | |
| _validate_boolean_value(self, 'request_parameter_supported') | |
| def validate_request_uri_parameter_supported(self): | |
| """OPTIONAL. Boolean value specifying whether the OP supports use of | |
| the request_uri parameter, with true indicating support. If omitted, | |
| the default value is true. | |
| """ | |
| _validate_boolean_value(self, 'request_uri_parameter_supported') | |
| def validate_require_request_uri_registration(self): | |
| """OPTIONAL. Boolean value specifying whether the OP requires any | |
| request_uri values used to be pre-registered using the request_uris | |
| registration parameter. Pre-registration is REQUIRED when the value | |
| is true. If omitted, the default value is false. | |
| """ | |
| _validate_boolean_value(self, 'require_request_uri_registration') | |
| def claim_types_supported(self): | |
| # If omitted, the implementation supports only normal Claims | |
| return self.get('claim_types_supported', ['normal']) | |
| def claims_parameter_supported(self): | |
| # If omitted, the default value is false. | |
| return self.get('claims_parameter_supported', False) | |
| def request_parameter_supported(self): | |
| # If omitted, the default value is false. | |
| return self.get('request_parameter_supported', False) | |
| def request_uri_parameter_supported(self): | |
| # If omitted, the default value is true. | |
| return self.get('request_uri_parameter_supported', True) | |
| def require_request_uri_registration(self): | |
| # If omitted, the default value is false. | |
| return self.get('require_request_uri_registration', False) | |
| def _validate_boolean_value(metadata, key): | |
| if key not in metadata: | |
| return | |
| if metadata[key] not in (True, False): | |
| raise ValueError(f'"{key}" MUST be boolean') | |