def oidc_callback(self): """ Exchange the auth code for actual credentials, then redirect to the originally requested page. """ # retrieve session and callback variables try: session_csrf_token = session.pop('oidc_csrf_token') state = json.loads(request.args['state']) csrf_token = state['csrf_token'] destination = state['destination'] code = request.args['code'] except (KeyError, ValueError): logger.debug("Can't retrieve CSRF token, state, or code", exc_info=True) return self.oidc_error() # check callback CSRF token passed to IdP # against session CSRF token held by user if csrf_token != session_csrf_token: logger.debug("CSRF token mismatch") return self.oidc_error() # make a request to IdP to exchange the auth code for OAuth credentials flow = self.flow_for_request() if 'scope' in request.args: scopes = set(util.string_to_scopes(request.args['scope'])) scopes |= set(util.string_to_scopes(flow.scope)) flow.scope = util.scopes_to_string(scopes) credentials = flow.step2_exchange(code, http=self.http) id_token = credentials.id_token if not self.is_id_token_valid(id_token): logger.debug("Invalid ID token") # None will allow all domains otherwise limit down to the specific domain. if self.google_apps_domain is not None: if not isinstance(self.google_apps_domain, list): self.google_apps_domain = [self.google_apps_domain] if id_token.get('hd') not in self.google_apps_domain: return self.oidc_error( "You must log in with an account from one of the following domains: {0}" .format(', '.join(self.google_apps_domain)), self.WRONG_GOOGLE_APPS_DOMAIN) return self.oidc_error() # store credentials by subject # when Google is the IdP, the subject is their G+ account number self.credentials_store[id_token['sub']] = credentials # set a persistent signed cookie containing the ID token # and redirect to the final destination # TODO: validate redirect destination response = self.redirect_to(destination) self.set_cookie_id_token(id_token) return response
def test_conversion(self): cases = [ (['a', 'b'], ['a', 'b']), ('', []), ('a', ['a']), ('a b c d e f', ['a', 'b', 'c', 'd', 'e', 'f']), ] for case, expected in cases: self.assertEqual(expected, util.string_to_scopes(case))