def login(self): # get request parameters from which we can determine the login phase authorization_code = self.params.get('code') error = self.params.get('error') error_message = self.params.get('error_message') state = self.params.get('state') if authorization_code or not self.user_authorization_url: if authorization_code: #=================================================================== # Phase 2 after redirect with success #=================================================================== self._log( logging.INFO, 'Continuing OAuth 2.0 authorization procedure after redirect.' ) # validate CSRF token if self.supports_csrf_protection: self._log( logging.INFO, 'Validating request by comparing request state with stored state.' ) stored_state = self._session_get('state') if not stored_state: raise FailureError('Unable to retrieve stored state!') elif not stored_state == state: raise FailureError( 'The returned state "{}" doesn\'t match with the stored state!' .format(state), url=self.user_authorization_url) self._log(logging.INFO, 'Request is valid.') else: self._log(logging.WARN, 'Skipping CSRF validation!') elif not self.user_authorization_url: #=================================================================== # Phase 1 without user authorization redirect. #=================================================================== self._log(logging.INFO, 'Starting OAuth 2.0 authorization procedure without ' + \ 'user authorization redirect.') # exchange authorization code for access token by the provider self._log( logging.INFO, 'Fetching access token from {}.'.format(self.access_token_url)) self.credentials.token = authorization_code request_elements = self.create_request_elements( request_type=self.ACCESS_TOKEN_REQUEST_TYPE, credentials=self.credentials, url=self.access_token_url, method='POST', redirect_uri=self.url, params=self.access_token_params, headers=self.access_token_headers) response = self._fetch(*request_elements) access_token = response.data.get('access_token', '') refresh_token = response.data.get('refresh_token', '') if response.status != 200 or not access_token: raise FailureError('Failed to obtain OAuth 2.0 access token from {}! HTTP status: {}, message: {}.'\ .format(self.access_token_url, response.status, response.content), original_message=response.content, status=response.status, url=self.access_token_url) self._log(logging.INFO, 'Got access token.') if refresh_token: self._log(logging.INFO, 'Got refresh access token.') # OAuth 2.0 credentials need access_token, refresh_token, token_type and expire_in. self.credentials.token = access_token self.credentials.refresh_token = refresh_token self.credentials.expire_in = response.data.get('expire_in') self.credentials.token_type = response.data.get('token_type', '') # sWe don't need these two guys anymore. self.credentials.consumer_key = '' self.credentials.consumer_secret = '' # update credentials self.credentials = self._x_credentials_parser( self.credentials, response.data) # create user self._update_or_create_user(response.data, self.credentials) #=================================================================== # We're done! #=================================================================== elif error or error_message: #=================================================================== # Phase 2 after redirect with error #=================================================================== error_reason = self.params.get('error_reason') error_description = self.params.get( 'error_description') or error_message if error_reason == 'user_denied': raise CancellationError(error_description, url=self.user_authorization_url) else: raise FailureError(error_description, url=self.user_authorization_url) elif not self.params: #=================================================================== # Phase 1 before redirect #=================================================================== self._log(logging.INFO, 'Starting OAuth 2.0 authorization procedure.') csrf = '' if self.supports_csrf_protection: # generate csfr csrf = self.csrf_generator() # and store it to session self._session_set('state', csrf) else: self._log(logging.WARN, 'Provider doesn\'t support CSRF validation!') request_elements = self.create_request_elements( request_type=self.USER_AUTHORIZATION_REQUEST_TYPE, credentials=self.credentials, url=self.user_authorization_url, redirect_uri=self.url, scope=self._x_scope_parser(self.scope), csrf=csrf, params=self.user_authorization_params) self._log( logging.INFO, 'Redirecting user to {}.'.format(request_elements.full_url)) self.redirect(request_elements.full_url)
def login(self): # get request parameters from which we can determine the login phase denied = self.params.get('denied') verifier = self.params.get('oauth_verifier', '') request_token = self.params.get('oauth_token', '') if request_token and verifier: # Phase 2 after redirect with success self._log( logging.INFO, 'Continuing OAuth 1.0a authorization procedure after redirect.' ) token_secret = self._session_get('token_secret') if not token_secret: raise FailureError( 'Unable to retrieve token secret from storage!') # Get Access Token self._log( logging.INFO, 'Fetching for access token from {0}.'.format( self.access_token_url)) self.credentials.token = request_token self.credentials.token_secret = token_secret request_elements = self.create_request_elements( request_type=self.ACCESS_TOKEN_REQUEST_TYPE, url=self.access_token_url, credentials=self.credentials, verifier=verifier, params=self.access_token_params) response = self._fetch(*request_elements) if not self._http_status_in_category(response.status, 2): raise FailureError('Failed to obtain OAuth 1.0a oauth_token from {0}! HTTP status code: {1}.'\ .format(self.access_token_url, response.status), original_message=response.content, status=response.status, url=self.access_token_url) self._log(logging.INFO, 'Got access token.') self.credentials.token = response.data.get('oauth_token', '') self.credentials.token_secret = response.data.get( 'oauth_token_secret', '') self.credentials = self._x_credentials_parser( self.credentials, response.data) self._update_or_create_user(response.data, self.credentials) #=================================================================== # We're done! #=================================================================== elif denied: # Phase 2 after redirect denied raise CancellationError('User denied the request token {0} during a redirect to {1}!'.\ format(denied, self.user_authorization_url), original_message=denied, url=self.user_authorization_url) else: # Phase 1 before redirect self._log(logging.INFO, 'Starting OAuth 1.0a authorization procedure.') # Fetch for request token request_elements = self.create_request_elements( request_type=self.REQUEST_TOKEN_REQUEST_TYPE, credentials=self.credentials, url=self.request_token_url, callback=self.url, params=self.request_token_params) self._log(logging.INFO, 'Fetching for request token and token secret.') response = self._fetch(*request_elements) # check if response status is OK if not self._http_status_in_category(response.status, 2): raise FailureError('Failed to obtain request token from {0}! HTTP status code: {1} content: {2}'\ .format(self.request_token_url, response.status, response.content), original_message=response.content, status=response.status, url=self.request_token_url) # extract request token request_token = response.data.get('oauth_token') if not request_token: raise FailureError( 'Response from {0} doesn\'t contain oauth_token parameter!' .format(self.request_token_url), original_message=response.content, url=self.request_token_url) # we need request token for user authorization redirect self.credentials.token = request_token # extract token secret and save it to storage token_secret = response.data.get('oauth_token_secret') if token_secret: # we need token secret after user authorization redirect to get access token self._session_set('token_secret', token_secret) else: raise FailureError( 'Failed to obtain token secret from {0}!'.format( self.request_token_url), original_message=response.content, url=self.request_token_url) self._log(logging.INFO, 'Got request token and token secret') # Create User Authorization URL request_elements = self.create_request_elements( request_type=self.USER_AUTHORIZATION_REQUEST_TYPE, credentials=self.credentials, url=self.user_authorization_url, params=self.user_authorization_params) self._log( logging.INFO, 'Redirecting user to {0}.'.format(request_elements.full_url)) self.redirect(request_elements.full_url)
def login(self): # Instantiate consumer self.store._log = self._log oi_consumer = consumer.Consumer(self.session, self.store) # handle realm and XRDS if there is only one query parameter if self.use_realm and len(self.params) == 1: realm_request = self.params.get(self.realm_param) xrds_request = self.params.get(self.xrds_param) else: realm_request = None xrds_request = None # determine type of request if realm_request: #=================================================================== # Realm HTML #=================================================================== self._log(logging.INFO, 'Writing OpenID realm HTML to the response.') xrds_location = '{u}?{x}={x}'.format(u=self.url, x=self.xrds_param) self.write( REALM_HTML.format(xrds_location=xrds_location, body=self.realm_body)) elif xrds_request: #=================================================================== # XRDS XML #=================================================================== self._log(logging.INFO, 'Writing XRDS XML document to the response.') self.set_header('Content-Type', 'application/xrds+xml') self.write(XRDS_XML.format(return_to=self.url)) elif self.params.get('openid.mode'): #=================================================================== # Phase 2 after redirect #=================================================================== self._log( logging.INFO, 'Continuing OpenID authentication procedure after redirect.') # complete the authentication process response = oi_consumer.complete(self.params, self.url) # on success if response.status == consumer.SUCCESS: data = {} # get user ID data['guid'] = response.getDisplayIdentifier() self._log(logging.INFO, 'Authentication successful.') # get user data from AX response ax_response = ax.FetchResponse.fromSuccessResponse(response) if ax_response and ax_response.data: self._log(logging.INFO, 'Got AX data.') ax_data = {} # convert iterable values to their first item for k, v in ax_response.data.iteritems(): if v and type(v) in (list, tuple): ax_data[k] = v[0] data['ax'] = ax_data # get user data from SREG response sreg_response = sreg.SRegResponse.fromSuccessResponse(response) if sreg_response and sreg_response.data: self._log(logging.INFO, 'Got SREG data.') data['sreg'] = sreg_response.data # get data from PAPE response pape_response = pape.Response.fromSuccessResponse(response) if pape_response and pape_response.auth_policies: self._log(logging.INFO, 'Got PAPE data.') data['pape'] = pape_response.auth_policies # create user self._update_or_create_user(data) #=============================================================== # We're done! #=============================================================== elif response.status == consumer.CANCEL: raise CancellationError( 'User cancelled the verification of ID "{0}"!'.format( response.getDisplayIdentifier())) elif response.status == consumer.FAILURE: raise FailureError(response.message) elif self.identifier: # As set in AuthenticationProvider.__init__ #=================================================================== # Phase 1 before redirect #=================================================================== self._log(logging.INFO, 'Starting OpenID authentication procedure.') # get AuthRequest object try: auth_request = oi_consumer.begin(self.identifier) except consumer.DiscoveryFailure as e: raise FailureError( 'Discovery failed for identifier {0}!'.format( self.identifier), url=self.identifier, original_message=e.message) self._log( logging.INFO, 'Service discovery for identifier {0} successful.'.format( self.identifier)) # add SREG extension # we need to remove required fields from optional fields because addExtension then raises an error self.sreg = [i for i in self.sreg if i not in self.sreg_required] auth_request.addExtension( sreg.SRegRequest(optional=self.sreg, required=self.sreg_required)) # add AX extension ax_request = ax.FetchRequest() # set AX schemas for i in self.ax: required = i in self.ax_required ax_request.add(ax.AttrInfo(i, required=required)) auth_request.addExtension(ax_request) # add PAPE extension auth_request.addExtension(pape.Request(self.pape)) # prepare realm and return_to URLs if self.use_realm: realm = return_to = '{u}?{r}={r}'.format(u=self.url, r=self.realm_param) else: realm = return_to = self.url url = auth_request.redirectURL(realm, return_to) if auth_request.shouldSendRedirect(): # can be redirected url = auth_request.redirectURL(realm, return_to) self._log(logging.INFO, 'Redirecting user to {0}.'.format(url)) self.redirect(url) else: # must be sent as POST # this writes a html post form with auto-submit self._log(logging.INFO, 'Writing an auto-submit HTML form to the response.') form = auth_request.htmlMarkup(realm, return_to, False, dict(id='openid_form')) self.write(form) else: raise OpenIDError('No identifier specified!')