1 # -*- coding: utf-8 -*-
3 oauthlib.oauth2.rfc6749
4 ~~~~~~~~~~~~~~~~~~~~~~~
6 This module is an implementation of various logic needed
7 for consuming and providing OAuth 2.0 RFC6749.
9 from __future__ import absolute_import, unicode_literals
11 from .base import Client
12 from ..parameters import prepare_grant_uri, prepare_token_request
13 from ..parameters import parse_authorization_code_response
14 from ..parameters import parse_token_response
17 class WebApplicationClient(Client):
19 """A client utilizing the authorization code grant workflow.
21 A web application is a confidential client running on a web
22 server. Resource owners access the client via an HTML user
23 interface rendered in a user-agent on the device used by the
24 resource owner. The client credentials as well as any access
25 token issued to the client are stored on the web server and are
26 not exposed to or accessible by the resource owner.
28 The authorization code grant type is used to obtain both access
29 tokens and refresh tokens and is optimized for confidential clients.
30 As a redirection-based flow, the client must be capable of
31 interacting with the resource owner's user-agent (typically a web
32 browser) and capable of receiving incoming requests (via redirection)
33 from the authorization server.
36 def __init__(self, client_id, code=None, **kwargs):
37 super(WebApplicationClient, self).__init__(client_id, **kwargs)
40 def prepare_request_uri(self, uri, redirect_uri=None, scope=None,
41 state=None, **kwargs):
42 """Prepare the authorization code request URI
44 The client constructs the request URI by adding the following
45 parameters to the query component of the authorization endpoint URI
46 using the "application/x-www-form-urlencoded" format, per `Appendix B`_:
48 :param redirect_uri: OPTIONAL. The redirect URI must be an absolute URI
49 and it should have been registerd with the OAuth
50 provider prior to use. As described in `Section 3.1.2`_.
52 :param scope: OPTIONAL. The scope of the access request as described by
53 Section 3.3`_. These may be any string but are commonly
54 URIs or various categories such as ``videos`` or ``documents``.
56 :param state: RECOMMENDED. An opaque value used by the client to maintain
57 state between the request and callback. The authorization
58 server includes this value when redirecting the user-agent back
59 to the client. The parameter SHOULD be used for preventing
60 cross-site request forgery as described in `Section 10.12`_.
62 :param kwargs: Extra arguments to include in the request URI.
64 In addition to supplied parameters, OAuthLib will append the ``client_id``
65 that was provided in the constructor as well as the mandatory ``response_type``
66 argument, set to ``code``::
68 >>> from oauthlib.oauth2 import WebApplicationClient
69 >>> client = WebApplicationClient('your_id')
70 >>> client.prepare_request_uri('https://example.com')
71 'https://example.com?client_id=your_id&response_type=code'
72 >>> client.prepare_request_uri('https://example.com', redirect_uri='https://a.b/callback')
73 'https://example.com?client_id=your_id&response_type=code&redirect_uri=https%3A%2F%2Fa.b%2Fcallback'
74 >>> client.prepare_request_uri('https://example.com', scope=['profile', 'pictures'])
75 'https://example.com?client_id=your_id&response_type=code&scope=profile+pictures'
76 >>> client.prepare_request_uri('https://example.com', foo='bar')
77 'https://example.com?client_id=your_id&response_type=code&foo=bar'
79 .. _`Appendix B`: http://tools.ietf.org/html/rfc6749#appendix-B
80 .. _`Section 2.2`: http://tools.ietf.org/html/rfc6749#section-2.2
81 .. _`Section 3.1.2`: http://tools.ietf.org/html/rfc6749#section-3.1.2
82 .. _`Section 3.3`: http://tools.ietf.org/html/rfc6749#section-3.3
83 .. _`Section 10.12`: http://tools.ietf.org/html/rfc6749#section-10.12
85 return prepare_grant_uri(uri, self.client_id, 'code',
86 redirect_uri=redirect_uri, scope=scope, state=state, **kwargs)
88 def prepare_request_body(self, client_id=None, code=None, body='',
89 redirect_uri=None, **kwargs):
90 """Prepare the access token request body.
92 The client makes a request to the token endpoint by adding the
93 following parameters using the "application/x-www-form-urlencoded"
94 format in the HTTP request entity-body:
96 :param client_id: REQUIRED, if the client is not authenticating with the
97 authorization server as described in `Section 3.2.1`_.
99 :param code: REQUIRED. The authorization code received from the
100 authorization server.
102 :param redirect_uri: REQUIRED, if the "redirect_uri" parameter was included in the
103 authorization request as described in `Section 4.1.1`_, and their
104 values MUST be identical.
106 :param kwargs: Extra parameters to include in the token request.
108 In addition OAuthLib will add the ``grant_type`` parameter set to
109 ``authorization_code``.
111 If the client type is confidential or the client was issued client
112 credentials (or assigned other authentication requirements), the
113 client MUST authenticate with the authorization server as described
114 in `Section 3.2.1`_::
116 >>> from oauthlib.oauth2 import WebApplicationClient
117 >>> client = WebApplicationClient('your_id')
118 >>> client.prepare_request_body(code='sh35ksdf09sf')
119 'grant_type=authorization_code&code=sh35ksdf09sf'
120 >>> client.prepare_request_body(code='sh35ksdf09sf', foo='bar')
121 'grant_type=authorization_code&code=sh35ksdf09sf&foo=bar'
123 .. _`Section 4.1.1`: http://tools.ietf.org/html/rfc6749#section-4.1.1
124 .. _`Section 3.2.1`: http://tools.ietf.org/html/rfc6749#section-3.2.1
126 code = code or self.code
127 return prepare_token_request('authorization_code', code=code, body=body,
128 client_id=self.client_id, redirect_uri=redirect_uri, **kwargs)
130 def parse_request_uri_response(self, uri, state=None):
131 """Parse the URI query for code and state.
133 If the resource owner grants the access request, the authorization
134 server issues an authorization code and delivers it to the client by
135 adding the following parameters to the query component of the
136 redirection URI using the "application/x-www-form-urlencoded" format:
138 :param uri: The callback URI that resulted from the user being redirected
139 back from the provider to you, the client.
140 :param state: The state provided in the authorization request.
143 The authorization code generated by the authorization server.
144 The authorization code MUST expire shortly after it is issued
145 to mitigate the risk of leaks. A maximum authorization code
146 lifetime of 10 minutes is RECOMMENDED. The client MUST NOT
147 use the authorization code more than once. If an authorization
148 code is used more than once, the authorization server MUST deny
149 the request and SHOULD revoke (when possible) all tokens
150 previously issued based on that authorization code.
151 The authorization code is bound to the client identifier and
155 If the "state" parameter was present in the authorization request.
157 This method is mainly intended to enforce strict state checking with
158 the added benefit of easily extracting parameters from the URI::
160 >>> from oauthlib.oauth2 import WebApplicationClient
161 >>> client = WebApplicationClient('your_id')
162 >>> uri = 'https://example.com/callback?code=sdfkjh345&state=sfetw45'
163 >>> client.parse_request_uri_response(uri, state='sfetw45')
164 {'state': 'sfetw45', 'code': 'sdfkjh345'}
165 >>> client.parse_request_uri_response(uri, state='other')
166 Traceback (most recent call last):
167 File "<stdin>", line 1, in <module>
168 File "oauthlib/oauth2/rfc6749/__init__.py", line 357, in parse_request_uri_response
169 back from the provider to you, the client.
170 File "oauthlib/oauth2/rfc6749/parameters.py", line 153, in parse_authorization_code_response
171 raise MismatchingStateError()
172 oauthlib.oauth2.rfc6749.errors.MismatchingStateError
174 response = parse_authorization_code_response(uri, state=state)
175 self._populate_attributes(response)