Register Grants#
There are four grant types defined by RFC6749, you can also create your own extended grant. Register the supported grant types to the authorization server.
Implicit Grant#
The implicit grant type is usually used in a browser, when resource owner granted the access, an access token is issued in the redirect URI, there is no missing implementation, which means it can be easily registered with:
from authlib.oauth2.rfc6749 import grants
# register it to grant endpoint
server.register_grant(grants.ImplicitGrant)
Implicit Grant is used by public clients which have no client_secret.
Default allowed Client Authentication Methods: none.
Resource Owner Password Credentials Grant#
The resource owner uses its username and password to exchange an access
token. This grant type should be used only when the client is trustworthy;
implement it with a subclass of
ResourceOwnerPasswordCredentialsGrant:
from authlib.oauth2.rfc6749 import grants
class PasswordGrant(grants.ResourceOwnerPasswordCredentialsGrant):
def authenticate_user(self, username, password):
user = User.query.filter_by(username=username).first()
if user.check_password(password):
return user
# register it to grant endpoint
server.register_grant(PasswordGrant)
Default allowed Client Authentication Methods: client_secret_basic.
You can add more in the subclass:
class PasswordGrant(grants.ResourceOwnerPasswordCredentialsGrant):
TOKEN_ENDPOINT_AUTH_METHODS = [
'client_secret_basic', 'client_secret_post'
]
Client Credentials Grant#
Client credentials grant type can access public resources and MAYBE the client’s creator’s resources, depending on how you issue tokens to this grant type. It can be easily registered with:
from authlib.oauth2.rfc6749 import grants
# register it to grant endpoint
server.register_grant(grants.ClientCredentialsGrant)
Default allowed Client Authentication Methods: client_secret_basic.
You can add more in the subclass:
class ClientCredentialsGrant(grants.ClientCredentialsGrant):
TOKEN_ENDPOINT_AUTH_METHODS = [
'client_secret_basic', 'client_secret_post'
]
Refresh Token Grant#
Many OAuth 2 providers do not implement a refresh token endpoint. Authlib
provides it as a grant type; implement it with a subclass of
RefreshTokenGrant:
from authlib.oauth2.rfc6749 import grants
class RefreshTokenGrant(grants.RefreshTokenGrant):
def authenticate_refresh_token(self, refresh_token):
item = Token.query.filter_by(refresh_token=refresh_token).first()
# define is_refresh_token_valid by yourself
# usually, you should check if refresh token is expired and revoked
if item and item.is_refresh_token_valid():
return item
def authenticate_user(self, credential):
return User.query.get(credential.user_id)
def revoke_old_credential(self, credential):
credential.revoked = True
db.session.add(credential)
db.session.commit()
# register it to grant endpoint
server.register_grant(RefreshTokenGrant)
Default allowed Client Authentication Methods: client_secret_basic.
You can add more in the subclass:
class RefreshTokenGrant(grants.RefreshTokenGrant):
TOKEN_ENDPOINT_AUTH_METHODS = [
'client_secret_basic', 'client_secret_post'
]
By default, RefreshTokenGrant will not issue a refresh_token in the token
response. Developers can change this behavior with:
class RefreshTokenGrant(grants.RefreshTokenGrant):
INCLUDE_NEW_REFRESH_TOKEN = True
Custom Grant Types#
It is also possible to create your own grant types. In Authlib, a Grant supports two endpoints:
Authorization Endpoint: which can handle requests with
response_type.Token Endpoint: which is the endpoint to issue tokens.
Creating a custom grant type with BaseGrant:
from authlib.oauth2.rfc6749.grants import (
BaseGrant, AuthorizationEndpointMixin, TokenEndpointMixin
)
class MyCustomGrant(BaseGrant, AuthorizationEndpointMixin, TokenEndpointMixin):
GRANT_TYPE = 'custom-grant-type-name'
def validate_authorization_request(self):
# only needed if using AuthorizationEndpointMixin
def create_authorization_response(self, grant_user):
# only needed if using AuthorizationEndpointMixin
def validate_token_request(self):
# only needed if using TokenEndpointMixin
def create_token_response(self):
# only needed if using TokenEndpointMixin
For a better understanding, you can read the source code of the built-in grant types. And there are extended grant types defined by other specs:
Grant Extensions#
Added in version 0.10.
Grants can accept extensions. Developers can pass extensions when registering grants:
authorization_server.register_grant(AuthorizationCodeGrant, [extension])
For instance, there is the CodeChallenge extension in Authlib:
server.register_grant(AuthorizationCodeGrant, [CodeChallenge(required=False)])
Learn more about CodeChallenge at RFC7636: Proof Key for Code Exchange by OAuth Public Clients.