Authorization

Authorization can be either explicit or implicit. The former require the user to actively authorize the client by being redirected to the authorization endpoint. There he/she is usually presented by a form and asked to either accept or deny access to certain scopes. These scopes can be thought of as Access Control Lists that are tied to certain privileges and categories of resources, such as write access to their status feed or read access to their profile. It is vital that the implications of granting access to a certain scope is very clear in the authorization form presented to the user. It is up to the provider to allow the user agree to all, a few or none of the scopes. Being flexible here is a great benefit to the user at the cost of added complexity in both the provider and clients.

Implicit authorization happens when the authorization happens before the OAuth flow, such as the user giving the client his/her password and username, or if there is a very high level of trust between the user, client and provider and no explicit authorization is necessary.

Examples of explicit authorization is the Authorization Code Grant and the Implicit Grant.

Examples of implicit authorization is the Resource Owner Password Credentials Grant and the Client Credentials Grant.

Pre Authorization Request

OAuth is known for it’s authorization page where the user accepts or denies access to a certain client and set of scopes. Before presenting the user with such a form you need to ensure the credentials the client supplied in the redirection to this page are valid.

# Initial setup
from your_validator import your_validator
server = WebApplicationServer(your_validator)

# Validate request
uri = 'https://example.com/authorize?client_id=foo&state=xyz
headers, body, http_method = {}, '', 'GET'

from oauthlib.oauth2 import FatalClientError
from your_framework import redirect
try:
    scopes, credentials = server.validate_authorization_request(
        uri, http_method, body, headers)
    # scopes will hold default scopes for client, i.e.
    ['https://example.com/userProfile', 'https://example.com/pictures']

    # credentials is a dictionary of
    {
        'client_id': 'foo',
        'redirect_uri': 'https://foo.com/welcome_back',
        'response_type': 'code',
        'state': 'randomstring',
    }
    # these credentials will be needed in the post authorization view and
    # should be persisted between. None of them are secret but take care
    # to ensure their integrity if embedding them in the form or cookies.
    from your_datastore import persist_credentials
    persist_credentials(credentials)

    # Present user with a nice form where client (id foo) request access to
    # his default scopes (omitted from request), after which you will
    # redirect to his default redirect uri (omitted from request).

except FatalClientError as e:
    # this is your custom error page
    from your_view_helpers import error_to_response
    return error_to_response(e)
Post Authorization Request

Generally, this is where you handle the submitted form. Rather than using validate_authorization_request we use create_authorization_response which in the case of Authorization Code Grant embed an authorization code in the client provided redirect uri.

# Initial setup
from your_validator import your_validator
server = WebApplicationServer(your_validator)

# Validate request
uri = 'https://example.com/post_authorize?client_id=foo
headers, body, http_method = {}, '', 'GET'

# Fetch the credentials saved in the pre authorization phase
from your_datastore import fetch_credentials
credentials = fetch_credentials()

# Fetch authorized scopes from the request
from your_framework import request
scopes = request.POST.get('scopes')

from oauthlib.oauth2 import FatalClientError, OAuth2Error
from your_framework import http_response
http_response(body, status=status, headers=headers)
try:
    headers, body, status = server.create_authorization_response(
        uri, http_method, body, headers, scopes, credentials)
    # headers = {'Location': 'https://foo.com/welcome_back?code=somerandomstring&state=xyz'}, this might change to include suggested headers related
    # to cache best practices etc.
    # body = '', this might be set in future custom grant types
    # status = 302, suggested HTTP status code

    return http_response(body, status=status, headers=headers)

except FatalClientError as e:
    # this is your custom error page
    from your_view_helpers import error_to_response
    return error_to_response(e)

except OAuth2Error as e:
    # Less grave errors will be reported back to client
    client_redirect_uri = credentials.get('redirect_uri')
    redirect(e.in_uri(client_redirect_uri))
class oauthlib.oauth2.AuthorizationEndpoint(default_response_type, default_token_type, response_types)[source]

Authorization endpoint - used by the client to obtain authorization from the resource owner via user-agent redirection.

The authorization endpoint is used to interact with the resource owner and obtain an authorization grant. The authorization server MUST first verify the identity of the resource owner. The way in which the authorization server authenticates the resource owner (e.g. username and password login, session cookies) is beyond the scope of this specification.

The endpoint URI MAY include an “application/x-www-form-urlencoded” formatted (per Appendix B) query component, which MUST be retained when adding additional query parameters. The endpoint URI MUST NOT include a fragment component:

https://example.com/path?query=component             # OK
https://example.com/path?query=component#fragment    # Not OK

Since requests to the authorization endpoint result in user authentication and the transmission of clear-text credentials (in the HTTP response), the authorization server MUST require the use of TLS as described in Section 1.6 when sending requests to the authorization endpoint:

# We will deny any request which URI schema is not with https

The authorization server MUST support the use of the HTTP “GET” method [RFC2616] for the authorization endpoint, and MAY support the use of the “POST” method as well:

# HTTP method is currently not enforced

Parameters sent without a value MUST be treated as if they were omitted from the request. The authorization server MUST ignore unrecognized request parameters. Request and response parameters MUST NOT be included more than once:

# Enforced through the design of oauthlib.common.Request
create_authorization_response(uri, http_method='GET', body=None, headers=None, scopes=None, credentials=None)[source]

Extract response_type and route to the designated handler.

validate_authorization_request(uri, http_method='GET', body=None, headers=None)[source]

Extract response_type and route to the designated handler.