def test_request_attr_mis_match(): redirect_uri = "http://example.com/redirect" client = Client(CLIENT_ID, client_authn_method=CLIENT_AUTHN_METHOD) client.redirect_uris = [redirect_uri] client.authorization_endpoint = "http://example.com/authorization" client.client_secret = "abcdefghijklmnop" client.keyjar[""] = KC_RSA client.behaviour = { "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"] } srv = Server() srv.keyjar = KEYJ areq = client.construct_AuthorizationRequest( request_args={ "scope": "openid", "response_type": ["code"], "max_age": 86400, "state": "foobar", }, request_param="request", ) for attr in ["state", "max_age", "client_id"]: del areq[attr] areq.lax = True req = srv.parse_authorization_request(query=areq.to_urlencoded()) assert req.verify()
def make_authentication_request(): print ('create authentication request') # consider storing a hash in state # what to hash in state might include cookie data, time, salt, etc... # force login in order to work around the Azure AD issue where a user may be logged in to the wrong domain. # Set prompt=login in the implicit flow request to force a new login state = rndstr() nounce = rndstr() request_args = { "response_type": "id_token code", "response_mode": "form_post", "state": state, "nonce": nounce, "prompt": "login", "redirect_uri": Settings.auth_redirect_url, "scope":"openid profile" } print (Settings.auth_client_id) client = Client(Settings.auth_client_id) auth_req = client.construct_AuthorizationRequest(request_args = request_args) provider_url = Settings.auth_provider_url if Settings.auth_tenant is not None: provider_url = provider_url.replace("{{tenant}}", Settings.auth_tenant) login_url = auth_req.request(provider_url) print(login_url) return redirect(login_url)
def test_userinfo_request(): cli = Client() cli.userinfo_endpoint = "http://example.com/userinfo" info = ARESP.to_urlencoded() cli.parse_response(AuthorizationResponse, info, sformat="urlencoded", state="state0") cli.parse_response(AccessTokenResponse, TRESP.to_json(), state="state0") path, body, method, h_args = cli.user_info_request(state="state0") assert path == "http://example.com/userinfo?access_token=access_token" assert method == "GET" assert body is None assert h_args == {} path, body, method, h_args = cli.user_info_request(method="POST", state="state0") assert path == "http://example.com/userinfo" assert method == "POST" assert body == "access_token=access_token" assert h_args == {'headers': { 'Content-type': 'application/x-www-form-urlencoded'}} path, body, method, h_args = cli.user_info_request(method="POST", state="state0") assert path == "http://example.com/userinfo" assert method == "POST" assert body == "access_token=access_token" assert h_args == {'headers': { 'Content-type': 'application/x-www-form-urlencoded'}}
def __init__(self, provider_configuration, redirect_uri): """ Args: provider_configuration (flask_pyoidc.provider_configuration.ProviderConfiguration) """ self._provider_configuration = provider_configuration self._client = Client(client_authn_method=CLIENT_AUTHN_METHOD, settings=provider_configuration.client_settings) # Token Introspection is implemented under extension sub-package of # the client in pyoidc. self._client_extension = ClientExtension( client_authn_method=CLIENT_AUTHN_METHOD, settings=provider_configuration.client_settings) # Client Credentials Flow is implemented under oauth2 sub-package of # the client in pyoidc. self._oauth2_client = Oauth2Client( client_authn_method=CLIENT_AUTHN_METHOD, message_factory=CCMessageFactory, settings=self._provider_configuration.client_settings) provider_metadata = provider_configuration.ensure_provider_metadata( self._client) self._client.handle_provider_config( ProviderConfigurationResponse(**provider_metadata.to_dict()), provider_metadata['issuer']) if self._provider_configuration.registered_client_metadata: client_metadata = self._provider_configuration.registered_client_metadata.to_dict( ) client_metadata.update(redirect_uris=list(redirect_uri)) self._store_registration_info(client_metadata) self._redirect_uri = redirect_uri
def pedir_token(request): cliente = Client( client_id=llave, client_authn_method={"client_secret_post": ClientSecretPost}) respuesta_cruda = json.dumps(dict(request.GET)) respuesta = cliente.parse_response(AuthorizationResponse, info=respuesta_cruda) estado_recibido = respuesta['state'] estado_almacenado = request.session['estado'] if estado_recibido == estado_almacenado: codigo = respuesta['code'] parametros = { "token_endpoint": endpoint_token, "code": codigo, "client_id": llave, "client_secret": secreto, "redirect_uri": callback } resultado = cliente.do_access_token_request( scope=["openid"], state=estado_recibido, request_args=parametros, authn_method="client_secret_post") usuario = resultado['id_token']['sub'] cedula = usuario[:usuario.find('@')] return HttpResponse("Bienvenido, usuario {}".format(cedula)) else: return HttpResponse( "Error: el estado enviado al endpoint de autorizacion no corresponde con el recibido." )
def get_proxy_token(refresh_token_data, *, user_agent=constants.USER_AGENT, scope=constants.FXA_PROXY_SCOPE, resource=constants.DEFAULT_PROXY_URL, ttl=constants.FXA_EXP_TOKEN_TIME, timeout=10.): client = Client(client_authn_method=None) provider_info = client.provider_config(constants.FXA_PROVIDER_URL) token_endpoint = client.token_endpoint #return resp.to_dict() http_req = urllib.request.Request( token_endpoint, data=json.dumps({ "client_id": constants.CLIENT_ID, "grant_type": "refresh_token", "refresh_token": refresh_token_data["refresh_token"], "scope": scope, "ttl": ttl, "ppid_seed": random.randrange(1024), "resource": resource, }).encode('ascii'), headers={ "User-Agent": user_agent, "Content-Type": "application/json", } ) with urllib.request.urlopen(http_req, None, timeout) as resp: coding = resp.headers.get_content_charset() coding = coding if coding is not None else 'utf-8-sig' decoder = codecs.getreader(coding)(resp) res = json.load(decoder) res["received_at"] = int(time.time()) return res
def init_app(self, app): try: self.client_id = app.config["NHS_OIDC_CLIENT_ID"] self.authorization_callback_url = app.config[ "NHS_OIDC_LOGIN_CALLBACK_URL"] self.registration_callback_url = app.config[ "NHS_OIDC_REGISTRATION_CALLBACK_URL"] self.scopes = [ "openid", "profile", "email", "phone", "profile_extended" ] self.vtr = '["P5.Cp.Cd", "P5.Cp.Ck", "P5.Cm"]' self.authority_url = app.config["NHS_OIDC_AUTHORITY_URL"] except ValueError as e: raise ValueError(f"Missing NHS OIDC configuration: {e!r}") self.client = Client(client_id=self.client_id, client_authn_method=CLIENT_AUTHN_METHOD) self.client.provider_config(self.authority_url) self.private_key = app.config["NHS_OIDC_LOGIN_PRIVATE_KEY"] if not self.private_key: private_key_path = app.config["NHS_OIDC_LOGIN_PRIVATE_KEY_PATH"] if not os.stat(private_key_path): raise ValueError( f"Missing private key file. Expected private key file at {self.private_key_path!r}" ) with open(private_key_path) as key_file: self.private_key = key_file.read()
def oidc_login(): state = rndstr() nonce = rndstr() client = Client(client_authn_method=CLIENT_AUTHN_METHOD) client.provider_config(OIDC_INFO_URL) info = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET} client_reg = RegistrationResponse(**info) client.store_registration_info(client_reg) args = { "client_id": client.client_id, "response_type": "code", "scope": ["openid"], "nonce": nonce, "redirect_uri": OIDC_REDIRECT_URI, "state": state } auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) # Save in cache Key: state => Value: nonce current_app.cache.set(state, nonce) return redirect(login_url, 303)
def _configure_client(self): config_file_path = JwtAuthenticationMethod.openid_client_config_path() if not os.path.exists(config_file_path): logger.info( 'OpenID Connect configuration ({}) not found, JWT' ' authentication is disabled'.format(config_file_path) ) return with open(config_file_path) as fp: config = json.loads(fp.read()) self._client = Client( client_authn_method=CLIENT_AUTHN_METHOD, verify_ssl='/etc/pki/tls/certs/ca-bundle.crt' ) self._client.provider_config(config['issuer']) client_registration = RegistrationResponse( client_id=config['client_id'], client_secret=config['client_secret'] ) self._client.store_registration_info(client_registration)
def web_flow(ctx): client = Client(client_authn_method=CLIENT_AUTHN_METHOD) issuer = f"{settings.AUTH_DEFAULT_HOST}/auth/realms/unikube" client.provider_config(issuer) state = rndstr() nonce = rndstr() # 1. run callback server from unikube.authentication.web import run_callback_server port = run_callback_server(state, nonce, client, ctx) # 2. send to login with redirect url. args = { "client_id": "cli", "response_type": ["token"], "response_mode": "form_post", "scope": ["openid"], "nonce": nonce, "state": state, "redirect_uri": f"http://localhost:{port}", } auth_req = client.construct_AuthorizationRequest(request_args=args) login_url = auth_req.request(client.authorization_endpoint) console.info("If your Browser does not open automatically, go to the following URL and login:") console.link(login_url) click.launch(login_url) return True
def test_should_register_dynamic_client_if_client_registration_info_is_given( self): registration_endpoint = self.PROVIDER_BASEURL + '/register' redirect_uris = [ 'https://client.example.com/redirect', 'https://client.example.com/redirect2' ] post_logout_redirect_uris = ['https://client.example.com/logout'] responses.add(responses.POST, registration_endpoint, json={ 'client_id': 'client1', 'client_secret': 'secret1', 'redirect_uris': redirect_uris, 'post_logout_redirect_uris': post_logout_redirect_uris }) provider_config = ProviderConfiguration( provider_metadata=self.provider_metadata( registration_endpoint=registration_endpoint), client_registration_info=ClientRegistrationInfo( redirect_uris=redirect_uris, post_logout_redirect_uris=post_logout_redirect_uris)) provider_config.register_client(Client(CLIENT_AUTHN_METHOD)) assert provider_config._client_metadata['client_id'] == 'client1' assert provider_config._client_metadata['client_secret'] == 'secret1' assert provider_config._client_metadata[ 'redirect_uris'] == redirect_uris assert provider_config._client_metadata[ 'post_logout_redirect_uris'] == post_logout_redirect_uris
def get_client(): """Method that prepare the oidc client. This method use lru_cache in order call the OIDC provider once per thread Today we only support OIDC providers (ISSUER) that expose a /.well-known/openid-configuration route At the moment to authenticate the RP to the OIDC provider we only support through client_id/secret_ID/rp_callback attributes. You must configure OIDC in AnyBlok configuration: * **oidc-provider-issuer**: The OIDC Provider urls (ie: https://gitlab.com) * **oidc-relying-party-callback**: The Relaying Party callback, once the user is authenticate against the OIDC provider he will be redirect to that uri to the RP service (ie: http://localhost:8080/callback). In general this value is also configured in your OIDC provider to avoid redirection issues. * **oidc-relying-party-client-id**: The client id provide by your OIDC provider * **oidc-relying-party-secret-id**: The secret id provide by your OIDC provider And optionally: * **oidc-scope**: Specify what access privileges are being requested for Access Tokens. `cf Requesting claims using scope values <https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims`_. a list of claims using coma separator. (default value: `openid,email`) * **oidc-userinfo-field**: Specify which field to use from the response of the OIDC provider `userinfo endpoint <https://openid.net/specs/ openid-connect-core-1_0.html#UserInfoResponse>`_. To make sure it's a known user. (default value: `email`). """ client = Client(client_authn_method=CLIENT_AUTHN_METHOD) for config in [ "oidc_provider_issuer", "oidc_relying_party_client_id", "oidc_relying_party_secret_id", "oidc_relying_party_callback", ]: if Configuration.get(config, None) is None: raise ValueError("You must provide {} parameter".format(config)) provider_info = client.provider_config( Configuration.get("oidc_provider_issuer")) info = { "client_id": Configuration.get("oidc_relying_party_client_id"), "client_secret": Configuration.get("oidc_relying_party_secret_id"), "redirect_uris": [Configuration.get("oidc_relying_party_callback")], } info.update(provider_info._dict) client_reg = RegistrationResponse(**info) client.store_registration_info(client_reg) return client
def test_construct_CheckSessionRequest(): cli = Client() cli.check_session_endpoint = "https://example.org/oauth2/check_session" csr = cli.construct_CheckSessionRequest( request_args={"id_token": "id_token"}) print csr assert ("%s" % csr) == 'id_token=id_token'
def oidc_client(webserver, oidc_provider, reverse): client = Client(client_authn_method=CLIENT_AUTHN_METHOD) client.provider_config(issuer=reverse("openid")) client.store_registration_info( RegistrationResponse(client_id=oidc_provider.client_id, client_secret=oidc_provider.client_secret)) return client
def test_construct_UserInfoRequest(): cli = Client() cli.userinfo_endpoint = "https://example.org/oauth2/userinfo" uir = cli.construct_UserInfoRequest( request_args={"access_token": "access_token"}) print uir assert ("%s" % uir) == "access_token=access_token"
def test_should_not_fetch_provider_metadata_if_given(self): provider_metadata = self.provider_metadata() provider_config = ProviderConfiguration( provider_metadata=provider_metadata, client_registration_info=ClientRegistrationInfo()) provider_config.ensure_provider_metadata(Client(CLIENT_AUTHN_METHOD)) assert provider_config._provider_metadata == provider_metadata
def get_client(): client = Client(client_id=settings.AUTH_CLIENT_ID, client_authn_method=CLIENT_AUTHN_METHOD) client.provider_config(issuer=settings.AUTH_SERVER) client.store_registration_info( RegistrationResponse(client_id=settings.AUTH_CLIENT_ID, client_secret=settings.AUTH_CLIENT_SECRET)) return client
def authenticate(self, uid): cherrypy.session["client"] = Client(verify_ssl=self.verify_ssl) # webfinger+registration self.rp.register_with_dynamic_provider(cherrypy.session, uid) # auth req redirect_url = self.rp.make_authentication_request(cherrypy.session) raise cherrypy.HTTPRedirect(redirect_url, 303)
def test_get_authorization_request(): client = Client() client.redirect_uris = ["https://www.example.com/authz"] client.client_id = "a1b2c3" args = {"response_type": ["code"]} ar = client.construct_AuthorizationRequest(request_args=args) assert ar["client_id"] == 'a1b2c3' assert ar["redirect_uri"] == 'https://www.example.com/authz' assert ar["response_type"] == ['code'] client = Client() client.client_id = "a1b2c3" args = {"response_type": ["code"], "redirect_uri": "https://www.example.com/authz"} ar = client.construct_AuthorizationRequest(request_args=args) assert ar["client_id"] == 'a1b2c3' assert ar["redirect_uri"] == 'https://www.example.com/authz' assert ar["response_type"] == ['code']
def prepare_client(): # http://pyoidc.readthedocs.io/en/latest/examples/rp.html # Instantiate a client client = Client(client_authn_method=CLIENT_AUTHN_METHOD) # Register the OP # endpoints are now loaded from a json file rather than defined here # DEV endpoints # issuer = "https://unity.eudat-aai.fz-juelich.de:443" # authorization_endpoint = "https://unity.eudat-aai.fz-juelich.de:443/oauth2-as/oauth2-authz" # token_endpoint = "https://unity.eudat-aai.fz-juelich.de:443/oauth2/token" # userinfo_endpoint = "https://unity.eudat-aai.fz-juelich.de:443/oauth2/userinfo" # PROD endpoints # issuer = "https://b2access.eudat.eu:443" # authorization_endpoint = "https://b2access.eudat.eu:443/oauth2-as/oauth2-authz" # token_endpoint = "https://b2access.eudat.eu:443/oauth2/token" # userinfo_endpoint = "https://b2access.eudat.eu:443/oauth2/userinfo" try: dir = os.path.dirname(__file__) provider_endpoints = json.load(open(dir + '/provider_endpoints.json')) issuer = provider_endpoints['issuer'] authorization_endpoint = provider_endpoints['authorization_endpoint'] token_endpoint = provider_endpoints['token_endpoint'] userinfo_endpoint = provider_endpoints['userinfo_endpoint'] except: print "Error when reading provider_endpoints.json" stdlogger.error("Error when reading provider_endpoints.json") issuer = "error" authorization_endpoint = "error" token_endpoint = "error" userinfo_endpoint = "error" op_info = ProviderConfigurationResponse(issuer=issuer, authorization_endpoint=authorization_endpoint, token_endpoint=token_endpoint, userinfo_endpoint=userinfo_endpoint) client.provider_info = op_info # Set our credentials (that we got from manually registering to B2Access), as well as the redirect URI try: dir = os.path.dirname(__file__) client_credentials = json.load(open(dir + '/client_credentials.json')) id = client_credentials['client_id'] secret = client_credentials['client_secret'] uri = client_credentials['client_redirect_uri'] except: print "Error when reading client_credential.json" stdlogger.error("Error when reading client_credential.json") id = "error" secret = "error" uri = "error" # /!\ Added the redirect URI here, else it's not defined later (in args ={[...] client.registration_response["redirect_uris"][0]) uris = [uri] info = {"client_id": id, "client_secret": secret, "redirect_uris": uris} client_reg = RegistrationResponse(**info) client.store_registration_info(client_reg) return client
def register_client(issuer): client = Client(client_authn_method=CLIENT_AUTHN_METHOD) client.provider_config(issuer) params = { 'redirect_uris': [settings.REDIRECT_URI], 'client_name': settings.SITE_NAME, } client.register(client.provider_info['registration_endpoint'], **params) return client
def oidc_callback(): # Instantiate again the client client = Client(client_authn_method=CLIENT_AUTHN_METHOD) info = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET} client_reg = RegistrationResponse(**info) client.store_registration_info(client_reg) args = { "client_id": client.client_id, "response_type": "code", "scope": ["openid"], "redirect_uri": OIDC_REDIRECT_URI, } auth_req = client.construct_AuthorizationRequest(request_args=args) client.provider_config(OIDC_INFO_URL) # Posted information query_string = request.url auth_response = client.parse_response(AuthorizationResponse, info=query_string, sformat="urlencoded") # We need to find a state/nonce pair that matches what we have nonce = current_app.cache.get(auth_response['state']) current_app.cache.delete(auth_response['state']) if "id_token" in auth_response and auth_response["id_token"][ "nonce"] != nonce: return make_response('', 500) # Request an access token an use it to require the user's information args = {"code": auth_response["code"]} client.do_access_token_request(state=auth_response["state"], request_args=args, authn_method="client_secret_basic") # This is the object with the user info user_info = client.do_user_info_request(state=auth_response["state"]) # Take the mail depending on the attribute they have saved it in mail = user_info[u'mail'] if not mail: mail = user_info[u'email'] # Validate that the user mail is in the DB user = User.query.filter_by(email=mail).first() if user is None: return make_response('Unauthorized user', 401) # Login the user and return login_user(user, remember=True) return redirect(url_for('welcome'))
def test_get_access_token_request(): resp = AuthorizationResponse(code="code", state="state") grant = Grant(1) grant.add_code(resp) client = Client() client.grant["openid"] = grant time.sleep(2) raises(GrantExpired, 'client.construct_AccessTokenRequest(state="openid")')
def setup_class(self): self.client = Client(CLIENT_ID, client_authn_method=CLIENT_AUTHN_METHOD) self.client.redirect_uris = ["http://example.com/redirect"] self.client.client_secret = CLIENT_SECRET self.client.keyjar[""] = KC_RSA self.client.behaviour = { "request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"] } self._state = ""
def _build_oidc_client(self): client = Client(client_authn_method=CLIENT_AUTHN_METHOD) provider_config = ProviderConfigurationResponse( **self.settings["oidc"]["provider"]["configuration"]) client.handle_provider_config(provider_config, provider_config["issuer"]) client.store_registration_info( RegistrationResponse( **self.settings["oidc"]["provider"]["registration"])) return client
def init_client_for_shortcut(openid_client_obj): client = Client(client_authn_method=CLIENT_AUTHN_METHOD) reg_info = { 'client_id': openid_client_obj.client_id, 'client_secret': openid_client_obj.client_secret, 'redirect_uris': [settings.REDIRECT_URI], } client_reg = RegistrationResponse(**reg_info) client.store_registration_info(client_reg) client.provider_config(openid_client_obj.issuer) return client
def create_oidc_client(issuer=None, registration_info=None): if "oidc" not in g: g.oidc = Client(client_authn_method=CLIENT_AUTHN_METHOD) config = get(f"{issuer}/.well-known/openid-configuration", headers={"Content-type": "application/json"}).json() provider_config = ProviderConfigurationResponse(**config) g.oidc.handle_provider_config(provider_config, issuer) g.oidc.store_registration_info( RegistrationResponse(**registration_info) ) g.oidc.redirect_uris.append(f"{g.oidc.registration_response['redirect_uris'][0]}/callback") return g.oidc
def init_oidc_client(app): oidc_client = Client(client_authn_method=CLIENT_AUTHN_METHOD) oidc_client.store_registration_info(RegistrationRequest(**app.config['CLIENT_REGISTRATION_INFO'])) provider = app.config['PROVIDER_CONFIGURATION_INFO']['issuer'] try: oidc_client.provider_config(provider) except ConnectionError as e: app.logger.critical('No connection to provider {!s}. Can not start without provider configuration.'.format( provider)) raise e return oidc_client
def get_client(self): client = Client( client_authn_method={ 'client_secret_post': ClientSecretPost, 'client_secret_basic': ClientSecretBasic }) client.provider_config(settings.AUTHMACHINE_URL) client.client_id = settings.AUTHMACHINE_CLIENT_ID client.client_secret = settings.AUTHMACHINE_CLIENT_SECRET client.verify_ssl = True return client
def test_client_get_grant(): cli = Client() resp = AuthorizationResponse(code="code", state="state") grant = Grant() grant.add_code(resp) cli.grant["state"] = grant gr1 = cli.grant_from_state("state") assert gr1.code == "code"