RFC7592: OAuth 2.0 Dynamic Client Registration Management Protocol¶
This section contains the generic implementation of RFC 7592. OAuth 2.0 Dynamic Client Registration Management Protocol allows developers edit and delete OAuth client via API through Authorization Server. This specification is an extension of RFC7591: OAuth 2.0 Dynamic Client Registration Protocol.
Client Configuration Endpoint¶
The endpoint URL identifies the client, for instance
/oauth/register/<client_id>. The registration access token returned by the
RFC7591: OAuth 2.0 Dynamic Client Registration Protocol registration endpoint is only valid for this client. The
endpoint calls check_client() on the
token, and denies the request when the token was issued to another client.
Before register the endpoint, developers MUST implement the missing methods:
from urllib.parse import urlparse
from authlib.oauth2.rfc7592 import ClientConfigurationEndpoint
class MyClientConfigurationEndpoint(ClientConfigurationEndpoint):
def authenticate_token(self, request):
# this method is used to authenticate the registration access
# token returned by the RFC7591 registration endpoint
auth_header = request.headers.get('Authorization')
bearer_token = auth_header.split()[1]
token = Token.get(bearer_token)
return token
def authenticate_client(self, request):
# read the client_id from the endpoint URL, not from the body:
# GET and DELETE requests have no body.
# The route parameter of the web framework can also be used.
path = urlparse(request.uri).path
client_id = path.rstrip('/').rsplit('/', 1)[-1]
return Client.get(client_id=client_id)
def revoke_access_token(self, token, request):
token.revoked = True
token.save()
def check_permission(self, client, request):
return client.editable
def delete_client(self, client, request):
client.delete()
def update_client(self, client, client_metadata, request):
client.set_client_metadata(client_metadata)
client.save()
return client
def generate_client_registration_info(self, client, request):
access_token = request.headers['Authorization'].split(' ')[1]
return {
'registration_client_uri': request.uri,
'registration_access_token': access_token,
}
def get_server_metadata(self):
return {
'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': ...,
'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': ...,
}
API Reference¶
- class authlib.oauth2.rfc7592.ClientConfigurationEndpoint(server=None, claims_classes=None)¶
- generate_client_registration_info(client, request)¶
Generate
`registration_client_uriandregistration_access_tokenfor RFC7592. By default this method returns the values sent in the current request. Developers MUST rewrite this method to return different registration information.:def generate_client_registration_info(self, client, request):{ access_token = request.headers['Authorization'].split(' ')[1] return { 'registration_client_uri': request.uri, 'registration_access_token': access_token, }
- Parameters:
client – the instance of OAuth client
request – formatted request instance
- authenticate_token(request)¶
Authenticate the registration access token of the request. Developers MUST implement this method in subclass:
def authenticate_token(self, request): auth = request.headers.get("Authorization") return get_token_by_auth(auth)
The token MUST implement
check_client(). Requests are denied when the token was not issued to the requested client.- Returns:
token instance
- authenticate_client(request)¶
Read the client from the client configuration endpoint URL. Developers MUST implement this method in subclass:
from urllib.parse import urlparse def authenticate_client(self, request): path = urlparse(request.uri).path client_id = path.rstrip("/").rsplit("/", 1)[-1] return Client.get(client_id=client_id)
The route parameter of the web framework can also be used.
- Returns:
client instance
- revoke_access_token(token, request)¶
Revoke a token access in case an invalid client has been requested. Developers MUST implement this method in subclass:
def revoke_access_token(self, token, request): token.revoked = True token.save()
- check_permission(client, request)¶
Checks whether the current client is allowed to be accessed, edited or deleted. Developers MUST implement it in subclass, e.g.:
def check_permission(self, client, request): return client.editable
- Returns:
boolean
- delete_client(client, request)¶
Delete authorization code from database or cache. Developers MUST implement it in subclass, e.g.:
def delete_client(self, client, request): client.delete()
- Parameters:
client – the instance of OAuth client
request – formatted request instance
- update_client(client, client_metadata, request)¶
Update the client in the database. Developers MUST implement this method in subclass:
def update_client(self, client, client_metadata, request): client.set_client_metadata( {**client.client_metadata, **client_metadata} ) client.save() return client
- Parameters:
client – the instance of OAuth client
client_metadata – a dict of the client claims to update
request – formatted request instance
- Returns:
client instance
- get_server_metadata()¶
Return server metadata which includes supported grant types, response types and etc.