def create_authn_request(self, acr_value=None): state = rndstr() nonce = rndstr() request_args = { "response_type": self.behaviour["response_type"], "scope": self.behaviour["scope"], "state": state, "nonce": nonce, "redirect_uri": self.registration_response["redirect_uris"][0] } if acr_value is not None: request_args["acr_values"] = acr_value cis = self.construct_AuthorizationRequest(request_args=request_args) logger.debug("request: %s" % cis) url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis, method="GET", request_args=request_args) logger.debug("body: %s" % body) logger.info("URL: %s" % url) logger.debug("ht_args: %s" % ht_args) return str(url), ht_args, state
def auth_request(self, state='', nonce='', **kwargs): if not state: state = rndstr() if not nonce: nonce = rndstr() req = self.client.construct_AuthorizationRequest( request_args={ 'client_id': self.client.client_id, 'response_type': 'code', 'scope': ['openid', 'profile'], 'redirect_uri': self.client.registration_response['redirect_uris'][0], 'state': state, 'nonce': nonce, 'kc_idp_hint': kwargs.get('idp_hint'), 'login_hint': kwargs.get('login_hint'), 'claims': { 'userinfo': { 'email': {'essential': True}, 'name': {'essential': True} } } } ) return req.request(self.client.authorization_endpoint)
def create_authn_request(self, session, acr_value=None, **kwargs): session["state"] = rndstr() session["nonce"] = rndstr() request_args = { "response_type": self.behaviour["response_type"], "scope": self.behaviour["scope"], "state": session["state"], "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0] } if acr_value is not None: request_args["acr_values"] = acr_value request_args.update(kwargs) cis = self.construct_AuthorizationRequest(request_args=request_args) logger.debug("request: %s" % cis) url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis, method="GET", request_args=request_args) logger.debug("body: %s", body) logger.info("URL: %s", url) logger.debug("ht_args: %s", ht_args) if isinstance(url, newstr): p3_bytes = bytes(url) url = p3_bytes.decode('utf-8', 'surrogateescape') resp = HttpResponseRedirect(url) if ht_args: for key, value in ht_args.items(): resp[key] = value logger.debug("resp_headers: %s" % ht_args) return resp
def get_authorization_request_url(self, session): """ Returns redirect URL for authorization via M-Pin system. After URL redirects back, pass query_string to validate_authorization to complete authorization with server. :arg session mutable dictionary that contains session variables """ client = self._create_client(session) # Regenerate state and nonce on each auth url request session[SESSION_MIRACL_STATE_KEY] = rndstr() session[SESSION_MIRACL_NONCE_KEY] = rndstr() args = { "client_id": client.client_id, "response_type": "code", "scope": ['openid', 'email', 'sub', 'name'], "nonce": session[SESSION_MIRACL_NONCE_KEY], "redirect_uri": client.registration_response["redirect_uris"][0], "state": session[SESSION_MIRACL_STATE_KEY] } _logger.debug(MIRACL_LOG_AUTHORIZATION_REQUEST, args) auth_req = client.construct_AuthorizationRequest(request_args=args) request = auth_req.request(client.authorization_endpoint) _logger.debug(MIRACL_LOG_AUTHORIZATION_REQUEST_URL, request) return request
def _authenticate(self): if 'client_id' not in self.client_registration_info: # do dynamic registration if self.logout_view: # handle support for logout with self.app.app_context(): self.client_registration_info['post_logout_redirect_uris'] = [url_for(self.logout_view.__name__, _external=True)] self.client.register(self.client.provider_info['registration_endpoint'], **self.client_registration_info) flask.session['destination'] = flask.request.url flask.session['state'] = rndstr() flask.session['nonce'] = rndstr() args = { 'client_id': self.client.client_id, 'response_type': 'code', 'scope': ['openid'], 'redirect_uri': self.client.registration_response['redirect_uris'][0], 'state': flask.session['state'], 'nonce': flask.session['nonce'], } args.update(self.extra_request_args) auth_req = self.client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(self.client.authorization_endpoint) return redirect(login_url)
def get_request_args(self, client, acr_value, session): """ :param client: Client instance :param acr_value: Authentication Context reference :param session: Session information :return: A set of Authorization request arguments """ request_args = { "response_type": self.flow_type, "scope": self.pool_config["scope"], "state": client.state, } if acr_value: request_args["acr_values"] = [acr_value] if self.flow_type == "token": request_args["nonce"] = rndstr(16) session["nonce"] = request_args["nonce"] else: use_nonce = getattr(self, "use_nonce", None) if use_nonce: request_args["nonce"] = rndstr(16) session["nonce"] = request_args["nonce"] logger.info("client args: %s" % list(client.__dict__.items()), ) logger.info("request_args: %s" % (request_args,)) return client, request_args
def store_session_handler(self, sh): sid = rndstr(24) while sid in self.session_conf: sid = rndstr(24) sh['sid'] = sid self.session_conf[sid] = sh return sid
def start_auth(self, context, request_info): """ See super class method satosa.backends.base#start_auth :type context: satosa.context.Context :type request_info: satosa.internal.InternalData """ oidc_nonce = rndstr() oidc_state = rndstr() state_data = { NONCE_KEY: oidc_nonce, STATE_KEY: oidc_state } context.state[self.name] = state_data args = { "scope": self.config["client"]["auth_req_params"]["scope"], "response_type": self.config["client"]["auth_req_params"]["response_type"], "client_id": self.client.client_id, "redirect_uri": self.client.registration_response["redirect_uris"][0], "state": oidc_state, "nonce": oidc_nonce } args.update(self.config["client"]["auth_req_params"]) auth_req = self.client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(self.client.authorization_endpoint) return Redirect(login_url)
def create_authn_request(self, session, acr_value=None, **kwargs): session["state"] = rndstr(32) request_args = { "response_type": self.behaviour["response_type"], "scope": self.behaviour["scope"], "state": session["state"], "redirect_uri": self.registration_response["redirect_uris"][0] } if self.oidc: session["nonce"] = rndstr(32) request_args['nonce'] = session['nonce'] if acr_value is not None: request_args["acr_values"] = acr_value request_args.update(kwargs) cis = self.construct_AuthorizationRequest(request_args=request_args) logger.debug("request: %s" % sanitize(cis)) url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis, method="GET", request_args=request_args) self.authz_req[request_args['state']] = cis logger.debug("body: %s" % sanitize(body)) logger.info("URL: %s" % sanitize(url)) logger.debug("ht_args: %s" % sanitize(ht_args)) resp = Redirect(str(url)) if ht_args: resp.headers.extend([(a, b) for a, b in ht_args.items()]) logger.debug("resp_headers: %s" % sanitize(resp.headers)) return resp
def start_auth(self, context, request_info): """ See super class method satosa.backends.base#start_auth :type context: satosa.context.Context :type request_info: satosa.internal_data.InternalRequest """ oidc_clients = self.get_oidc_clients() try: client_key = next(iter(oidc_clients.client.keys())) except: client_key = False if client_key: client = oidc_clients[client_key] else: client = oidc_clients.dynamic_client(self.config.OP_URL) client_key = client.provider_info["issuer"] jwks_uri = "" try: for issuer in client.keyjar.issuer_keys: if issuer != "": jwks_uri = client.keyjar.issuer_keys[issuer][0].source except: pass nonce = rndstr() oidc_state = rndstr() state_data = { StateKeys.OP: client_key, StateKeys.NONCE: nonce, StateKeys.STATE: oidc_state } if "client_registration" not in self.config.CLIENTS[client_key]: save_state_dict = { StateKeys.TOKEN_ENDPOINT: client.token_endpoint, StateKeys.CLIENT_ID: client.client_id, StateKeys.CLIENT_SECRET: client.client_secret, StateKeys.JWKS_URI: jwks_uri, StateKeys.USERINFO_ENDPOINT: client.userinfo_endpoint } else: save_state_dict = {} state_data.update(save_state_dict) context.state.add(self.config.STATE_ID, state_data) try: resp = client.create_authn_request( context.state, oidc_state, nonce, self.config.ACR_VALUES ) except Exception: raise else: return resp
def srv(): class Bunch(dict): def __init__(self, **kw): dict.__init__(self, kw) self.__dict__ = self return Bunch(symkey=rndstr(), seed=rndstr().encode("utf-8"), iv=os.urandom(16), cookie_name="xyzxyz")
def create_authnrequest(self, environ, server_env, start_response, session, acr_value, state): try: client = session['client'] session.set_acr_value(client.authorization_endpoint, acr_value) request_args = { "response_type": self.flow_type, "scope": server_env["SCOPE"], "state": state, } if acr_value is not None: request_args["acr_values"] = acr_value if self.flow_type == "token": request_args["nonce"] = rndstr(16) session['nonce'] = request_args["nonce"] else: use_nonce = getattr(self, "use_nonce", None) if use_nonce: request_args["nonce"] = rndstr(16) session['nonce'] = request_args["nonce"] logger.info("client args: %s", list(client.__dict__.items())) logger.info("request_args: %s", request_args) # User info claims except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) return self.result( environ, start_response, server_env, (False, "Cannot find the OP! Please view your configuration.")) try: cis = client.construct_AuthorizationRequest( request_args=request_args) logger.debug("request: %s", cis) url, body, ht_args, cis = client.uri_and_body( AuthorizationRequest, cis, method="GET", request_args=request_args) logger.debug("body: %s", body) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) return self.result(environ, start_response, server_env, ( False, "Authorization request can not be performed!")) logger.info("URL: %s", url) logger.debug("ht_args: %s", ht_args) session['client'] = client resp_headers = [("Location", str(url))] if ht_args: resp_headers.extend([(a, b) for a, b in ht_args.items()]) logger.debug("resp_headers: %s", resp_headers) start_response("302 Found", resp_headers) return []
def __init__(self, conv, inut, sh, **kwargs): super(AsyncAuthn, self).__init__(conv, inut, sh, **kwargs) self.op_args["endpoint"] = conv.entity.provider_info[ "authorization_endpoint"] conv.state = rndstr() self.req_args["state"] = conv.state conv.nonce = rndstr() self.req_args["nonce"] = conv.nonce
def __init__(self, conv, inut, sh, **kwargs): super(SyncAuthn, self).__init__(conv, inut, sh, **kwargs) self.op_args["endpoint"] = conv.entity.provider_info[ "authorization_endpoint"] conv.state = rndstr() self.req_args["state"] = conv.state conv.nonce = rndstr() self.req_args["nonce"] = conv.nonce # defaults self.req_args['scope'] = ['openid'] self.req_args['response_type'] = 'code'
def _collect_user_info(self, session, userinfo_claims=None): ava = provider.Provider._collect_user_info(self, session, userinfo_claims) _src = "src1" if "aggregated" in self.claims_type: # add some aggregated claims extra = Message(eye_color="blue", shoe_size=8) _jwt = extra.to_jwt(algorithm="none") ava["_claim_names"] = Message(eye_color=_src, shoe_size=_src) a_claims = {_src: {"JWT": _jwt}} ava["_claim_sources"] = Message(**a_claims) elif "distributed" in self.claims_type: urlbase = self.name if urlbase[-1] != '/': urlbase += '/' _tok = rndstr() self.claim_access_token[_tok] = {"age": 30} ava["_claim_names"] = Message(age=_src) d_claims = { _src: {"endpoint": urlbase + "claim", "access_token": _tok}} ava["_claim_sources"] = Message(**d_claims) if "uisub" in self.behavior_type: ava["sub"] = "foobar" return ava
def test_pkce_token(): kb = KeyBundle(JWKS["keys"]) kj = KeyJar() kj.issuer_keys[''] = [kb] constructor = JWTToken('A', keyjar=kj, lt_pattern={'': 900}, iss='https://example.com/as', sign_alg='RS256', encrypt=True) sid = rndstr(32) session_info = { 'sub': 'subject_id', 'client_id': 'https://example.com/rp', 'response_type': ['code'], 'authzreq': '{}' } _cli = Client(config={'code_challenge': {'method': 'S512', 'length': 96}}) args, cv = _cli.add_code_challenge() access_grant = constructor( sid, sinfo=session_info, kid='sign1', code_challenge=args['code_challenge'], code_challenge_method=args['code_challenge_method']) _info = constructor.get_info(access_grant) assert _info['code_challenge_method'] == args['code_challenge_method'] assert _info['code_challenge'] == args['code_challenge']
def new_map(self, sid=''): if not sid: sid = rndstr(16) op = self.provider_cls(**self.as_args) op.baseurl = '{}{}'.format(self.base_url, sid) op.name = op.baseurl _conv = Conversation(None, op, None) _conv.events = self.as_args['event_db'] _conv.data = self.data sh = SessionHandler(flows=self.flows, order=self.order) sh.init_session(self.profile) self._db[sid] = { 'op': op, 'conv': _conv, 'ts': time.time(), 'selected': {}, 'session_handler': sh, 'headlines': self.headlines } return sid
def create_authn_request(self, session, acr_value=None, **kwargs): session["state"] = rndstr(32) request_args = { "response_type": self.behaviour["response_type"], "state": session["state"], "redirect_uri": self.registration_response["redirect_uris"][0] } try: request_args["scope"] = self.behaviour["scope"] except KeyError: pass request_args.update(kwargs) cis = self.construct_AuthorizationRequest(request_args=request_args) logger.debug("request: %s" % cis) url, body, ht_args, cis = self.uri_and_body(AuthorizationRequest, cis, method="GET", request_args=request_args) self.authz_req[request_args['state']] = cis logger.debug("body: %s" % body) logger.info("URL: %s" % url) logger.debug("ht_args: %s" % ht_args) resp = Redirect(str(url)) if ht_args: resp.headers.extend([(a, b) for a, b in ht_args.items()]) logger.debug("resp_headers: %s" % resp.headers) return resp
def assertion_jwt(cli, keys, audience, algorithm, lifetime=600): _now = utc_time_sans_frac() at = AuthnToken(iss=cli.client_id, sub=cli.client_id, aud=audience, jti=rndstr(32), exp=_now + lifetime, iat=_now) return at.to_jwt(key=keys, algorithm=algorithm)
def test_parse_enc(self): sid = rndstr(32) session_info = SESSION_INFO _jwe = self.access_token(sid, sinfo=session_info, kid='sign1') _info = self.access_token.get_info(_jwe) assert _info
def init_client(self, session, key): """ Instantiate a client to talk to the AS :param session: :param key: :return: client instance """ logger.debug("FLOW type: %s" % self.flow_type) if self.baseurl.endswith("/"): callback = self.baseurl + key else: callback = "%s/%s" % (self.baseurl, key) try: _ = self.pool_config["client"][key]["client_id"] client = self.static(callback, key) except KeyError: client = self.dynamic(callback, session, key) try: client.state = session["state"] except KeyError: client.state = session["state"] = rndstr() return client
def test_stateID(): seed = rndstr().encode("utf-8") sid0 = stateID("http://example.com/home", seed) sid1 = stateID("http://example.com/home", seed) assert sid0 assert sid1 assert sid0 != sid1
def store(self, item): """ Insert an item, if the _id already exists in the DB overwrite that item :param item: PermissionDescription instance """ if '_id' in item: _id = item['_id'] try: old_item = self[_id] except KeyError: if '_rev' not in item: item['_rev'] = 1 else: _rev = old_item['_rev'] item['_rev'] = _rev + 1 del self.db[_id] self.db[_id] = item else: _id = rndstr(32) item['_id'] = _id item['_rev'] = 1 self.db[_id] = item return _id
def __init__(self, config, base_url, seed='', jwks_info=None, verify_ssl=True): """ :param config: Imported configuration module :return: """ self.client = {} self.client_cls = Client self.config = config self.seed = seed or rndstr(16) self.seed = self.seed.encode('utf8') self.path = {} self.base_url = base_url self.jwks_info = jwks_info self.verify_ssl = verify_ssl for key, val in config.CLIENTS.items(): if self.jwks_info: _val = val.copy() _val.update(self.jwks_info) else: _val = val if key == "": continue else: self.client[key] = self.create_client(**_val)
def _distributed(self, info): # store the user info so it can be accessed later access_token = rndstr() self.info_store[access_token] = info return UserClaimsResponse(endpoint=self.claims_userinfo_endpoint, access_token=access_token, claims_names=info.keys())
def stateID(url, seed): """The hash of the time + server path + a seed makes an unique SID for each session. :param url: The base URL for this site :return: The hex version of the digest """ # Seed may be bytes or unicode try: seed = seed.encode() except AttributeError: pass ident = md5() ident.update(repr(time.time()).encode()) ident.update(url.encode()) ident.update(seed) # Mix in some randomness, as time.time() does not have enough # accuracy on all platforms to make this unique for identical # seeds and urls. # The accuracy can be pretty bad, around 20ms, unless one uses # one of the high precision timers (e.g. py3 timeit.default_timer()) # that use stuff like the performance counters in the CPU. # But even that can and does break on VMs, where the performance counters # are virtualized too, so better play safe than sorry here. ident.update(rndstr(8).encode()) return ident.hexdigest()
def init_srv(self, srv): if srv: self.srv = srv for param in ["seed", "iv"]: if not getattr(srv, param, None): setattr(srv, param, rndstr().encode("utf-8"))
def create_new_client(self, request, restrictions): """ :param request: The Client registration request :param restrictions: Restrictions on the client :return: The client_id """ _cinfo = request.to_dict() self.match_client_request(_cinfo) # create new id and secret _id = rndstr(12) while _id in self.cdb: _id = rndstr(12) _cinfo["client_id"] = _id _cinfo["client_secret"] = secret(self.seed, _id) _cinfo["client_id_issued_at"] = utc_time_sans_frac() _cinfo["client_secret_expires_at"] = utc_time_sans_frac() + \ self.secret_lifetime # If I support client info endpoint if ClientInfoEndpoint in self.endp: _cinfo["registration_access_token"] = rndstr(32) _cinfo["registration_client_uri"] = "%s%s%s?client_id=%s" % ( self.name, self.client_info_url, ClientInfoEndpoint.etype, _id) if "redirect_uris" in request: _cinfo["redirect_uris"] = self._uris_to_tuples( request["redirect_uris"]) self.load_keys(request, _id, _cinfo["client_secret"]) try: _behav = self.behavior['client_registration'] except KeyError: pass else: self.verify_correct(_cinfo, _behav) self.set_token_policy(_id, _cinfo) self.cdb[_id] = _cinfo return _id
def test_enc_create(self): sid = rndstr(32) session_info = SESSION_INFO _jwe = self.access_token(sid, sinfo=session_info, kid='sign1') assert _jwe assert len(_jwe.split('.')) == 5 # very simple JWE check
def test_set_state(): _info = setup_conv() oper = AsyncAuthn(_info['conv'], _info['io'], None) oper.conv.state = rndstr(16) args = None set_state(oper, args) assert oper.op_args['state'] == oper.conv.state
def test_create_with_aud(self): sid = rndstr(32) session_info = SESSION_INFO _jwt = self.access_token(sid, sinfo=session_info, kid='sign1', aud=['https://example.com/rs']) assert _jwt
def test_create(self): sid = rndstr(32) session_info = SESSION_INFO _jwt = self.access_token(sid, sinfo=session_info, kid='sign1') assert _jwt assert len(_jwt.split('.')) == 3 # very simple JWS check
def registration_endpoint(self, data): try: req = self.parse_registration_request(data, "json") except ValueError: req = self.parse_registration_request(data) client_secret = rndstr() expires = utc_time_sans_frac() + self.registration_expires_in kwargs = {} if "client_id" not in req: client_id = rndstr(10) registration_access_token = rndstr(20) _client_info = req.to_dict() kwargs.update(_client_info) _client_info.update({ "client_secret": client_secret, "info": req.to_dict(), "expires": expires, "registration_access_token": registration_access_token, "registration_client_uri": "register_endpoint" }) self.client[client_id] = _client_info kwargs["registration_access_token"] = registration_access_token kwargs["registration_client_uri"] = "register_endpoint" try: del kwargs["operation"] except KeyError: pass else: client_id = req.client_id _cinfo = self.client[req.client_id] _cinfo["info"].update(req.to_dict()) _cinfo["client_secret"] = client_secret _cinfo["expires"] = expires resp = RegistrationResponse(client_id=client_id, client_secret=client_secret, client_secret_expires_at=expires, **kwargs) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response
def _create_client(self, session): if SESSION_MIRACL_STATE_KEY not in session: session[SESSION_MIRACL_STATE_KEY] = rndstr() if SESSION_MIRACL_NONCE_KEY not in session: session[SESSION_MIRACL_NONCE_KEY] = rndstr() client = Client(client_authn_method=CLIENT_AUTHN_METHOD) client.handle_provider_config(self.provider_info, issuer=self.issuer) client_reg = RegistrationResponse(**self.info) client.store_registration_info(client_reg) if SESSION_MIRACL_TOKEN_KEY in session: access_token = AccessTokenResponse().from_dict( session[SESSION_MIRACL_TOKEN_KEY]) client.registration_access_token = access_token return client
def _distributed(self, info): # store the user info so it can be accessed later access_token = rndstr() self.info_store[access_token] = info return UserClaimsResponse( endpoint=self.claims_userinfo_endpoint, access_token=access_token, claims_names=info.keys(), )
def write_jwks_uri(op, op_arg): _name = "jwks_{}.json".format(rndstr()) filename = "./static/{}".format(_name) with open(filename, "w") as f: f.write(json.dumps(op_arg["jwks"])) f.close() op.jwks_uri = "{}static/{}".format(op_arg["baseurl"], _name) op.jwks_name = filename
def create(self, redirect_uris=None, policy_uri="", logo_uri="", jwks_uri="", **kwargs): if redirect_uris is None: print( 'Enter redirect_uris one at the time, end with a blank line: ') redirect_uris = [] while True: redirect_uri = input('?: ') if redirect_uri: redirect_uris.append(redirect_uri) else: break if not policy_uri: policy_uri = input("Enter policy_uri or just return: ") if not logo_uri: logo_uri = input("Enter logo_uri or just return: ") client_id = rndstr(12) while client_id in self.cdb.keys(): client_id = rndstr(12) client_secret = secret(self.seed, client_id) info = { "client_secret": client_secret, "client_id": client_id, "client_salt": rndstr(8), "redirect_uris": pack_redirect_uri(redirect_uris), } if policy_uri: info["policy_uri"] = policy_uri if logo_uri: info["logo_uri"] = logo_uri if jwks_uri: info['jwks_uri'] = jwks_uri self.cdb[client_id] = info return self.cdb[client_id]
def __init__(self, name, sdb, cdb, authn_broker, authz, client_authn, symkey="", urlmap=None, iv=0, default_scope="", ca_bundle=None, verify_ssl=True, default_acr="", baseurl='', server_cls=Server): self.name = name self.sdb = sdb self.cdb = cdb self.server = server_cls(ca_certs=ca_bundle, verify_ssl=verify_ssl) self.authn_broker = authn_broker if authn_broker is None: # default cookie function self.cookie_func = CookieDealer(srv=self).create_cookie else: self.cookie_func = self.authn_broker[0][0].create_cookie for item in self.authn_broker: item.srv = self self.authz = authz self.client_authn = client_authn self.symkey = symkey self.seed = rndstr().encode("utf-8") self.iv = iv or os.urandom(16) self.cookie_name = "pyoidc" self.default_scope = default_scope self.sso_ttl = 0 self.default_acr = default_acr if urlmap is None: self.urlmap = {} else: self.urlmap = urlmap self.response_type_map = { "code": code_response, "token": token_response, "none": none_response, } self.session_cookie_name = "pyoic_session" self.baseurl = baseurl self.keyjar = None self.trace = None self.events = None
def auth(request): global auth_endpoint session_info = {} session_info['state'] = rndstr() session_info['nonce'] = rndstr() redirect_uri = 'https://{}{}'.format(request.get_host(), reverse('openid_auth_callback')) params = { 'response_type': 'code', 'state': session_info['state'], 'nonce': session_info['nonce'], 'client_id': CLIENT_ID, 'redirect_uri': redirect_uri, 'scope': ' '.join(SCOPES_SUPPORTED) } return redirect(auth_endpoint + '?' + urlencode(params))
def study(request): """This view redirects the user to Dataporten to request authorization for fetching information about the user's groups membership, which can be used to verify eligibility for membership of Online.""" # If the user already is a member we can return early. However, if we're in testing, we want to skip the check. if settings.DATAPORTEN.get("STUDY").get("ENABLED") and request.user.is_member: messages.info(request, "Du er allerede registrert som medlem.") return redirect("profiles_active", active_tab="membership") logger.debug( "{} wants to automatically confirm study programme through Dataporten.".format( request.user ), extra={"user": request.user}, ) client = client_setup(DATAPORTEN_CLIENT_ID, DATAPORTEN_CLIENT_SECRET) # Generate random values used to verify that it's the same user when in the callback. state = rndstr() nonce = rndstr() request.session["dataporten_study_state"] = state request.session["dataporten_study_nonce"] = nonce args = { "client_id": DATAPORTEN_CLIENT_ID, "response_type": "code", "scope": DATAPORTEN_SCOPES, "redirect_uri": DATAPORTEN_REDIRECT_URI, "nonce": nonce, "state": state, } logger.debug( "Constructing authorization request and redirecting user to authorize through Dataporten.", extra={"user": request.user}, ) auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) return redirect(login_url)
def save_oauth_session_params(account, lifetime=10, redirect_msg=None, created_at=None): session = get_session() user_session_state = rndstr() user_session_nonce = rndstr() expired_at = datetime.datetime.utcnow() + datetime.timedelta( seconds=lifetime) oauth_session_params = models.OAuthRequest(account=account, state=user_session_state, nonce=user_session_nonce, expired_at=expired_at, redirect_msg=redirect_msg, created_at=created_at) oauth_session_params.save(session=session) session.commit() # pylint: disable=no-member session.expunge(oauth_session_params) # pylint: disable=no-member return None
def authenticate(request): if request.user and request.user.is_authenticated: return redirect('/') request.session["state"] = rndstr() request.session["nonce"] = rndstr() args = { "client_id": _client.client_id, "response_type": "code", "scope": ["profile", "company_info"], "nonce": request.session["nonce"], "redirect_uri": _client.registration_response["redirect_uris"][0], "state": request.session["state"], } auth_req = _client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(_client.authorization_endpoint) return redirect(login_url)
def index(): session["state"] = rndstr() session["nonce"] = rndstr() args = { "client_id": client_id, "response_type": "code", "scope": ["openid", "user_name", "mail"], "nonce": session["nonce"], "redirect_uri": redirect_uri, "post_logout_redirect_uri": post_logout_redirect_uri, "state": session["state"] } auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) return '<a href="{0}">Click here to login</a>'.format(login_url)
def create_authn_request(self, session, *, acr_value=None, extra_args=None): session["state"] = rndstr() session["nonce"] = rndstr() request_args = { "response_type": self.behaviour["response_type"], "scope": self.behaviour["scope"], "state": session["state"], "nonce": session["nonce"], "redirect_uri": self.registration_response["redirect_uris"][0] } if acr_value is None: acr_value = self.behaviour.get('acr_value') if acr_value is not None: request_args["acr_values"] = acr_value if extra_args is not None: request_args.update(extra_args) cis = self.construct_AuthorizationRequest(request_args=request_args) logger.debug("request: %s" % cis) url, body, ht_args, cis = self.uri_and_body( AuthorizationRequest, cis, method="GET", request_args=request_args, ) logger.debug("body: %s" % body) logger.info("URL: %s" % url) logger.debug("ht_args: %s" % ht_args) resp = HttpResponseRedirect(str(url)) if ht_args: for key, value in ht_args.items(): resp[key] = value logger.debug("resp_headers: %s" % ht_args) return resp
def _authenticate(self): if 'client_id' not in self.client_registration_info: logger.debug('performing dynamic client registration') # do dynamic registration if self.logout_view: # handle support for logout with self.app.app_context(): post_logout_redirect_uri = url_for( self.logout_view.__name__, _external=True) logger.debug('built post_logout_redirect_uri=%s', post_logout_redirect_uri) self.client_registration_info[ 'post_logout_redirect_uris'] = [ post_logout_redirect_uri ] registration_response = self.client.register( self.client.provider_info['registration_endpoint'], **self.client_registration_info) logger.debug('client registration response: %s', registration_response.to_json()) flask.session['destination'] = flask.request.url flask.session['state'] = rndstr() flask.session['nonce'] = rndstr() args = { 'client_id': self.client.client_id, 'response_type': 'code', 'scope': ['openid'], 'redirect_uri': self.client.registration_response['redirect_uris'][0], 'state': flask.session['state'], 'nonce': flask.session['nonce'], } args.update(self.extra_request_args) auth_req = self.client.construct_AuthorizationRequest( request_args=args) logger.debug('sending authentication request: %s', auth_req.to_json()) login_url = auth_req.request(self.client.authorization_endpoint) return redirect(login_url)
def auth_main(request): """ Function: auth ---------------------------- Redirects to B2Access for authentication """ request.session["connecting"] = 1 request.session["popup_state"] = "ongoing" # http://pyoidc.readthedocs.io/en/latest/examples/rp.html # Auth code request.session["nonce"] = rndstr() request.session["state"] = rndstr() args = {"client_id": client.client_id, "response_type": "code", "scope": ["openid", "USER_PROFILE"], "nonce": request.session["nonce"], "redirect_uri": client.registration_response["redirect_uris"][0], "state": request.session["state"]} auth_req = client.construct_AuthorizationRequest(request_args=args) # /!\ client.authorization_endpoint used in the example is not defined (or it's an empty string maybe) # using client.provider_info["authorization_endpoint"] instead login_url = auth_req.request(client.provider_info["authorization_endpoint"]) return redirect(login_url)
def test_create(self): sid = rndstr(32) session_info = SESSION_INFO _jwt = self.access_token(sid, sinfo=session_info, kid='sign1', lifetime=1200) assert _jwt assert len(_jwt.split('.')) == 3 # very simple JWS check
def key(self, user="", areq=None): """ Return a key - the session id - that are based on some session connected data. :param user: User id :param areq: The authorization request :return: A hash """ csum = hashlib.new("sha224") csum.update(rndstr(32).encode("utf-8")) return csum.hexdigest() # 56 bytes long, 224 bits
def login_shi(): session["state"] = rndstr() session["nonce"] = rndstr() claims_request = ClaimsRequest( userinfo=Claims( uiucedu_uin={"essential": True} ) ) args = { "client_id": client.client_id, "response_type": "code", "scope": Config.SCOPES, "claims": claims_request, "nonce": session["nonce"], "redirect_uri": client.registration_response["redirect_uris"][0], "state": session["state"] } auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) return Redirect(login_url)
def test_no_sub_or_sid(self): lt = LogoutToken( iss="https://example.com", aud=["https://rp.example.org"], events={BACK_CHANNEL_LOGOUT_EVENT: {}}, iat=utc_time_sans_frac(), jti=rndstr(16), ) with pytest.raises(ValueError): lt.verify()
def study(request): """This view redirects the user to Dataporten to request authorization for fetching information about the user's groups membership, which can be used to verify eligibility for membership of Online.""" # If the user already is a member we can return early. However, if we're in testing, we want to skip the check. if settings.DATAPORTEN.get('STUDY').get('ENABLED') and request.user.is_member: messages.info(request, 'Du er allerede registrert som medlem.') return redirect('profiles_active', active_tab='membership') logger.debug( '{} wants to automatically confirm study programme through Dataporten.'.format(request.user), extra={'user': request.user} ) client = client_setup(DATAPORTEN_CLIENT_ID, DATAPORTEN_CLIENT_SECRET) # Generate random values used to verify that it's the same user when in the callback. state = rndstr() nonce = rndstr() request.session['dataporten_study_state'] = state request.session['dataporten_study_nonce'] = nonce args = { 'client_id': DATAPORTEN_CLIENT_ID, 'response_type': 'code', 'scope': DATAPORTEN_SCOPES, 'redirect_uri': DATAPORTEN_REDIRECT_URI, 'nonce': nonce, 'state': state, } logger.debug( 'Constructing authorization request and redirecting user to authorize through Dataporten.', extra={'user': request.user} ) auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) return redirect(login_url)
def test_wrong_iss(self): lt = LogoutToken( iss="https://example.com", aud=["https://rp.example.org"], events={BACK_CHANNEL_LOGOUT_EVENT: {}}, iat=utc_time_sans_frac(), jti=rndstr(16), sub="https://example.com/sub", ) with pytest.raises(NotForMe): lt.verify(iss="https://rp.example.org")
def test_wrong_event(self): lt = LogoutToken( iss="https://example.com", aud=["https://rp.example.org"], events={"http://schemas.openid.net/event/other}": {}}, jti=rndstr(16), iat=utc_time_sans_frac(), sub="https://example.com/sub", ) with pytest.raises(ValueError): lt.verify()
def test_with_sub(self): # All the required claims. Note there must be a sub, a sid or both lt = LogoutToken( iss="https://example.com", aud=["https://rp.example.org"], events={BACK_CHANNEL_LOGOUT_EVENT: {}}, iat=utc_time_sans_frac(), jti=rndstr(16), sub="https://example.com/sub", ) assert lt.verify()
def logout(request): redirect_uri = 'https://{}'.format(request.get_host()) params = { 'id_token_hint': request.user.id_token, 'state': rndstr(), 'post_logout_redirect_uri': redirect_uri } system_logout(request) return redirect(end_session_endpoint + '?' + urlencode(params))
def init_srv(self, srv): if not srv: return self.srv = srv symkey = getattr(self.srv, "symkey", None) if symkey is not None and symkey == "": msg = "CookieDealer.srv.symkey cannot be an empty value" raise ImproperlyConfigured(msg) if not getattr(srv, "seed", None): setattr(srv, "seed", rndstr().encode("utf-8"))
def test_wrong_event_content(self): lt = LogoutToken( iss="https://example.com", aud=["https://rp.example.org"], events={BACK_CHANNEL_LOGOUT_EVENT: {"foo": "bar"}}, jti=rndstr(16), iat=utc_time_sans_frac(), sub="https://example.com/sub", ) with pytest.raises(ValueError): lt.verify()
def _authenticate(self, client, interactive=True): if not client.is_registered(): self._register_client(client) flask.session['destination'] = flask.request.url # Use silent authentication for session refresh # This will not show login prompt to the user extra_auth_params = {} if not interactive: extra_auth_params['prompt'] = 'none' auth_req = client.authentication_request(state=rndstr(), nonce=rndstr(), extra_auth_params=extra_auth_params) flask.session['auth_request'] = auth_req.to_json() login_url = client.login_url(auth_req) auth_params = dict(parse_qsl(login_url.split('?')[1])) flask.session['fragment_encoded_response'] = AuthResponseHandler.expect_fragment_encoded_response(auth_params) return redirect(login_url)