1212from django .views .decorators .debug import sensitive_post_parameters
1313from django .views .generic import FormView , View
1414
15+ # JB
16+ from django .forms import model_to_dict
17+ from django .core .serializers .json import DjangoJSONEncoder
18+ from django .db .models import Model
19+
1520from ..exceptions import OAuthToolkitError
1621from ..forms import AllowForm
1722from ..http import OAuth2ResponseRedirect
@@ -65,8 +70,100 @@ def redirect(self, redirect_to, application):
6570
6671RFC3339 = "%Y-%m-%dT%H:%M:%SZ"
6772
73+ class AuthorizationMixin :
74+ def get_context (self , request , * args , ** kwargs ):
75+ try :
76+ scopes , credentials = self .validate_authorization_request (request )
77+ except OAuthToolkitError as error :
78+ # Application is not available at this time.
79+ return self .error_response (error , application = None )
80+
81+ prompt = request .GET .get ("prompt" )
82+ if prompt == "login" :
83+ return self .handle_prompt_login ()
84+
85+ all_scopes = get_scopes_backend ().get_all_scopes ()
86+ kwargs ["scopes_descriptions" ] = [all_scopes [scope ] for scope in scopes ]
87+ kwargs ["scopes" ] = scopes
88+ # at this point we know an Application instance with such client_id exists in the database
89+
90+ # TODO: Cache this!
91+ application = get_application_model ().objects .get (client_id = credentials ["client_id" ])
92+
93+ kwargs ["application" ] = application
94+ kwargs ["client_id" ] = credentials ["client_id" ]
95+ kwargs ["redirect_uri" ] = credentials ["redirect_uri" ]
96+ kwargs ["response_type" ] = credentials ["response_type" ]
97+ kwargs ["state" ] = credentials ["state" ]
98+ if "code_challenge" in credentials :
99+ kwargs ["code_challenge" ] = credentials ["code_challenge" ]
100+ if "code_challenge_method" in credentials :
101+ kwargs ["code_challenge_method" ] = credentials ["code_challenge_method" ]
102+ if "nonce" in credentials :
103+ kwargs ["nonce" ] = credentials ["nonce" ]
104+ if "claims" in credentials :
105+ kwargs ["claims" ] = json .dumps (credentials ["claims" ])
106+
107+ self .oauth2_data = kwargs
108+
109+ # Check to see if the user has already granted access and return
110+ # a successful response depending on "approval_prompt" url parameter
111+ require_approval = request .GET .get ("approval_prompt" , oauth2_settings .REQUEST_APPROVAL_PROMPT )
112+
113+ try :
114+ # If skip_authorization field is True, skip the authorization screen even
115+ # if this is the first use of the application and there was no previous authorization.
116+ # This is useful for in-house applications-> assume an in-house applications
117+ # are already approved.
118+ if application .skip_authorization :
119+ uri , headers , body , status = self .create_authorization_response (
120+ request = self .request , scopes = " " .join (scopes ), credentials = credentials , allow = True
121+ )
122+ return self .redirect (uri , application )
123+
124+ elif require_approval == "auto" :
125+ tokens = (
126+ get_access_token_model ()
127+ .objects .filter (
128+ user = request .user , application = kwargs ["application" ], expires__gt = timezone .now ()
129+ )
130+ .all ()
131+ )
132+
133+ # check past authorizations regarded the same scopes as the current one
134+ for token in tokens :
135+ if token .allow_scopes (scopes ):
136+ uri , headers , body , status = self .create_authorization_response (
137+ request = self .request ,
138+ scopes = " " .join (scopes ),
139+ credentials = credentials ,
140+ allow = True ,
141+ )
142+ return self .redirect (uri , application )
143+
144+ except OAuthToolkitError as error :
145+ return self .error_response (error , application )
146+ return kwargs
147+
148+ class AuthorizationJSONView (BaseAuthorizationView , AuthorizationMixin ):
149+ def get (self , request , * args , ** kwargs ):
150+ context = self .get_context (request , * args , ** kwargs )
151+ return HttpResponse (
152+ content = json .dumps (context , cls = self .ExtendedEncoder ),
153+ status = 200 )
68154
69- class AuthorizationView (BaseAuthorizationView , FormView ):
155+ def post (self , request , * args , ** kwargs ):
156+ # handle JSON post, sanitization etc.
157+ pass
158+
159+ class ExtendedEncoder (DjangoJSONEncoder ):
160+ def default (self , o ):
161+ if isinstance (o , Model ):
162+ return model_to_dict (o )
163+ else :
164+ return super ().default (o )
165+
166+ class AuthorizationView (BaseAuthorizationView , FormView , AuthorizationMixin ):
70167 """
71168 Implements an endpoint to handle *Authorization Requests* as in :rfc:`4.1.1` and prompting the
72169 user with a form to determine if she authorizes the client application to access her data.
@@ -128,7 +225,6 @@ def form_valid(self, form):
128225
129226 scopes = form .cleaned_data .get ("scope" )
130227 allow = form .cleaned_data .get ("allow" )
131-
132228 try :
133229 uri , headers , body , status = self .create_authorization_response (
134230 request = self .request , scopes = scopes , credentials = credentials , allow = allow
@@ -141,82 +237,10 @@ def form_valid(self, form):
141237 return self .redirect (self .success_url , application )
142238
143239 def get (self , request , * args , ** kwargs ):
144- try :
145- scopes , credentials = self .validate_authorization_request (request )
146- except OAuthToolkitError as error :
147- # Application is not available at this time.
148- return self .error_response (error , application = None )
149-
150- prompt = request .GET .get ("prompt" )
151- if prompt == "login" :
152- return self .handle_prompt_login ()
153-
154- all_scopes = get_scopes_backend ().get_all_scopes ()
155- kwargs ["scopes_descriptions" ] = [all_scopes [scope ] for scope in scopes ]
156- kwargs ["scopes" ] = scopes
157- # at this point we know an Application instance with such client_id exists in the database
158-
159- # TODO: Cache this!
160- application = get_application_model ().objects .get (client_id = credentials ["client_id" ])
161-
162- kwargs ["application" ] = application
163- kwargs ["client_id" ] = credentials ["client_id" ]
164- kwargs ["redirect_uri" ] = credentials ["redirect_uri" ]
165- kwargs ["response_type" ] = credentials ["response_type" ]
166- kwargs ["state" ] = credentials ["state" ]
167- if "code_challenge" in credentials :
168- kwargs ["code_challenge" ] = credentials ["code_challenge" ]
169- if "code_challenge_method" in credentials :
170- kwargs ["code_challenge_method" ] = credentials ["code_challenge_method" ]
171- if "nonce" in credentials :
172- kwargs ["nonce" ] = credentials ["nonce" ]
173- if "claims" in credentials :
174- kwargs ["claims" ] = json .dumps (credentials ["claims" ])
175-
176- self .oauth2_data = kwargs
177- # following two loc are here only because of https://code.djangoproject.com/ticket/17795
240+ context = self .get_context (request , * args , ** kwargs )
178241 form = self .get_form (self .get_form_class ())
179- kwargs ["form" ] = form
180-
181- # Check to see if the user has already granted access and return
182- # a successful response depending on "approval_prompt" url parameter
183- require_approval = request .GET .get ("approval_prompt" , oauth2_settings .REQUEST_APPROVAL_PROMPT )
184-
185- try :
186- # If skip_authorization field is True, skip the authorization screen even
187- # if this is the first use of the application and there was no previous authorization.
188- # This is useful for in-house applications-> assume an in-house applications
189- # are already approved.
190- if application .skip_authorization :
191- uri , headers , body , status = self .create_authorization_response (
192- request = self .request , scopes = " " .join (scopes ), credentials = credentials , allow = True
193- )
194- return self .redirect (uri , application )
195-
196- elif require_approval == "auto" :
197- tokens = (
198- get_access_token_model ()
199- .objects .filter (
200- user = request .user , application = kwargs ["application" ], expires__gt = timezone .now ()
201- )
202- .all ()
203- )
204-
205- # check past authorizations regarded the same scopes as the current one
206- for token in tokens :
207- if token .allow_scopes (scopes ):
208- uri , headers , body , status = self .create_authorization_response (
209- request = self .request ,
210- scopes = " " .join (scopes ),
211- credentials = credentials ,
212- allow = True ,
213- )
214- return self .redirect (uri , application )
215-
216- except OAuthToolkitError as error :
217- return self .error_response (error , application )
218-
219- return self .render_to_response (self .get_context_data (** kwargs ))
242+ context ["form" ] = form
243+ return self .render_to_response (self .get_context_data (** context ))
220244
221245 def handle_prompt_login (self ):
222246 path = self .request .build_absolute_uri ()
0 commit comments