def test_totp_validate(self): """test flow with otp stages""" sleep(1) # Setup TOTP Device user = USER() device = TOTPDevice.objects.create(user=user, confirmed=True, digits=6) flow: Flow = Flow.objects.get(slug="default-authentication-flow") FlowStageBinding.objects.create( target=flow, order=30, stage=AuthenticatorValidateStage.objects.create()) self.driver.get(self.url("authentik_core:if-flow", flow_slug=flow.slug)) self.login() # Get expected token totp = TOTP(device.bin_key, device.step, device.t0, device.digits, device.drift) flow_executor = self.get_shadow_root("ak-flow-executor") validation_stage = self.get_shadow_root( "ak-stage-authenticator-validate", flow_executor) code_stage = self.get_shadow_root( "ak-stage-authenticator-validate-code", validation_stage) code_stage.find_element(By.CSS_SELECTOR, "input[name=code]").send_keys(totp.token()) code_stage.find_element(By.CSS_SELECTOR, "input[name=code]").send_keys(Keys.ENTER) self.wait_for_url(self.if_admin_url("/library")) self.assert_user(USER())
def test_authorization_logout(self): """test OpenID Provider flow with logout""" sleep(1) # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-implicit-consent") provider = OAuth2Provider.objects.create( name="grafana", client_type=ClientTypes.CONFIDENTIAL, client_id=self.client_id, client_secret=self.client_secret, rsa_key=CertificateKeyPair.objects.first(), redirect_uris="http://localhost:3000/login/generic_oauth", authorization_flow=authorization_flow, ) provider.property_mappings.set( ScopeMapping.objects.filter(scope_name__in=[ SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE ])) provider.save() Application.objects.create( name="Grafana", slug=APPLICATION_SLUG, provider=provider, ) self.driver.get("http://localhost:3000") self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click() self.login() self.wait_for_url("http://localhost:3000/?orgId=1") self.driver.get("http://localhost:3000/profile") self.assertEqual( self.driver.find_element(By.CLASS_NAME, "page-header__title").text, USER().name, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=name]").get_attribute("value"), USER().name, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=email]").get_attribute("value"), USER().email, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=login]").get_attribute("value"), USER().email, ) self.driver.get("http://localhost:3000/logout") self.wait_for_url( self.url( "authentik_providers_oauth2:end-session", application_slug=APPLICATION_SLUG, )) self.driver.find_element(By.ID, "logout").click()
def test_authorization_consent_explicit(self): """test OpenID Provider flow (default authorization flow with explicit consent)""" sleep(1) # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-explicit-consent" ) provider = OAuth2Provider.objects.create( name=self.application_slug, authorization_flow=authorization_flow, client_type=ClientTypes.CONFIDENTIAL, client_id=self.client_id, client_secret=self.client_secret, rsa_key=CertificateKeyPair.objects.first(), redirect_uris="http://localhost:9009/implicit/", ) provider.property_mappings.set( ScopeMapping.objects.filter( scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE] ) ) provider.save() app = Application.objects.create( name=self.application_slug, slug=self.application_slug, provider=provider, ) self.container = self.setup_client() self.driver.get("http://localhost:9009/implicit/") sleep(2) self.login() self.wait.until( ec.presence_of_element_located((By.CSS_SELECTOR, "ak-flow-executor")) ) flow_executor = self.get_shadow_root("ak-flow-executor") consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor) self.assertIn( app.name, consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text, ) consent_stage.find_element( By.CSS_SELECTOR, ("[type=submit]"), ).click() self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre"))) sleep(1) body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text) self.assertEqual(body["profile"]["nickname"], USER().username) self.assertEqual(body["profile"]["name"], USER().name) self.assertEqual(body["profile"]["email"], USER().email)
def test_authorization_consent_implied(self): """test OAuth Provider flow (default authorization flow with implied consent)""" # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-implicit-consent" ) provider = OAuth2Provider.objects.create( name="grafana", client_id=self.client_id, client_secret=self.client_secret, client_type=ClientTypes.CONFIDENTIAL, redirect_uris="http://localhost:3000/login/github", authorization_flow=authorization_flow, ) Application.objects.create( name="Grafana", slug="grafana", provider=provider, ) self.driver.get("http://localhost:3000") self.driver.find_element(By.CLASS_NAME, "btn-service--github").click() self.login() self.wait_for_url("http://localhost:3000/?orgId=1") self.driver.get("http://localhost:3000/profile") self.assertEqual( self.driver.find_element(By.CLASS_NAME, "page-header__title").text, USER().username, ) self.assertEqual( self.driver.find_element(By.CSS_SELECTOR, "input[name=name]").get_attribute( "value" ), USER().username, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=email]" ).get_attribute("value"), USER().email, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=login]" ).get_attribute("value"), USER().username, )
def initial_stages(self): """Fill out initial stages""" # Identification stage, click enroll flow_executor = self.get_shadow_root("ak-flow-executor") identification_stage = self.get_shadow_root( "ak-stage-identification", flow_executor ) wait = WebDriverWait(identification_stage, self.wait_timeout) wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#enroll"))) identification_stage.find_element(By.CSS_SELECTOR, "#enroll").click() # First prompt stage flow_executor = self.get_shadow_root("ak-flow-executor") prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor) wait = WebDriverWait(prompt_stage, self.wait_timeout) wait.until( ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=username]")) ) prompt_stage.find_element(By.CSS_SELECTOR, "input[name=username]").send_keys( "foo" ) prompt_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys( USER().username ) prompt_stage.find_element( By.CSS_SELECTOR, "input[name=password_repeat]" ).send_keys(USER().username) prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click() # Second prompt stage flow_executor = self.get_shadow_root("ak-flow-executor") prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor) wait = WebDriverWait(prompt_stage, self.wait_timeout) wait.until( ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=name]")) ) prompt_stage.find_element(By.CSS_SELECTOR, "input[name=name]").send_keys( "some name" ) prompt_stage.find_element(By.CSS_SELECTOR, "input[name=email]").send_keys( "*****@*****.**" ) prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
def test_totp_setup(self): """test TOTP Setup stage""" flow: Flow = Flow.objects.get(slug="default-authentication-flow") self.driver.get(self.url("authentik_core:if-flow", flow_slug=flow.slug)) self.login() self.wait_for_url(self.if_admin_url("/library")) self.assert_user(USER()) self.driver.get( self.url( "authentik_flows:configure", stage_uuid=AuthenticatorTOTPStage.objects.first().stage_uuid, )) flow_executor = self.get_shadow_root("ak-flow-executor") totp_stage = self.get_shadow_root("ak-stage-authenticator-totp", flow_executor) wait = WebDriverWait(totp_stage, self.wait_timeout) wait.until( ec.presence_of_element_located( (By.CSS_SELECTOR, "input[name=otp_uri]"))) otp_uri = totp_stage.find_element( By.CSS_SELECTOR, "input[name=otp_uri]").get_attribute("value") # Parse the OTP URI, extract the secret and get the next token otp_args = urlparse(otp_uri) self.assertEqual(otp_args.scheme, "otpauth") otp_qs = parse_qs(otp_args.query) secret_key = b32decode(otp_qs["secret"][0]) totp = TOTP(secret_key) totp_stage.find_element(By.CSS_SELECTOR, "input[name=code]").send_keys(totp.token()) totp_stage.find_element(By.CSS_SELECTOR, "input[name=code]").send_keys(Keys.ENTER) sleep(3) self.assertTrue( TOTPDevice.objects.filter(user=USER(), confirmed=True).exists())
def test_login(self): """test default login flow""" self.driver.get( self.url( "authentik_core:if-flow", flow_slug="default-authentication-flow", )) self.login() self.wait_for_url(self.if_admin_url("/library")) self.assert_user(USER())
def test_static_setup(self): """test Static OTP Setup stage""" flow: Flow = Flow.objects.get(slug="default-authentication-flow") self.driver.get(self.url("authentik_core:if-flow", flow_slug=flow.slug)) self.login() self.wait_for_url(self.if_admin_url("/library")) self.assert_user(USER()) self.driver.get( self.url( "authentik_flows:configure", stage_uuid=AuthenticatorStaticStage.objects.first().stage_uuid, )) # Remember the current URL as we should end up back here destination_url = self.driver.current_url flow_executor = self.get_shadow_root("ak-flow-executor") authenticator_stage = self.get_shadow_root( "ak-stage-authenticator-static", flow_executor) token = authenticator_stage.find_element( By.CSS_SELECTOR, ".ak-otp-tokens li:nth-child(1)").text authenticator_stage.find_element(By.CSS_SELECTOR, "button[type=submit]").click() self.wait_for_url(destination_url) sleep(1) self.assertTrue( StaticDevice.objects.filter(user=USER(), confirmed=True).exists()) device = StaticDevice.objects.filter(user=USER(), confirmed=True).first() self.assertTrue( StaticToken.objects.filter(token=token, device=device).exists())
def test_sp_initiated_implicit(self): """test SAML Provider flow SP-initiated flow (implicit consent)""" # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-implicit-consent") provider: SAMLProvider = SAMLProvider.objects.create( name="saml-test", acs_url="http://localhost:9009/saml/acs", audience="authentik-e2e", issuer="authentik-e2e", sp_binding=SAMLBindings.POST, authorization_flow=authorization_flow, signing_kp=CertificateKeyPair.objects.first(), ) provider.property_mappings.set(SAMLPropertyMapping.objects.all()) provider.save() Application.objects.create( name="SAML", slug="authentik-saml", provider=provider, ) self.container = self.setup_client(provider) self.driver.get("http://localhost:9009") self.login() self.wait_for_url("http://localhost:9009/") body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text) self.assertEqual( body["attr"] ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"], [USER().name], ) self.assertEqual( body["attr"] ["http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"], [USER().username], ) self.assertEqual( body["attr"] ["http://schemas.goauthentik.io/2021/02/saml/username"], [USER().username], ) self.assertEqual( body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"], [str(USER().pk)], ) self.assertEqual( body["attr"] ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"], [USER().email], ) self.assertEqual( body["attr"] ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"], [USER().email], )
def test_password_change(self): """test password change flow""" # Ensure that password stage has change_flow set flow = Flow.objects.get( slug="default-password-change", designation=FlowDesignation.STAGE_CONFIGURATION, ) stage = PasswordStage.objects.get( name="default-authentication-password") stage.configure_flow = flow stage.save() new_password = generate_client_secret() self.driver.get( self.url( "authentik_core:if-flow", flow_slug="default-authentication-flow", )) self.login() self.wait_for_url(self.if_admin_url("/library")) self.driver.get( self.url( "authentik_flows:configure", stage_uuid=PasswordStage.objects.first().stage_uuid, )) flow_executor = self.get_shadow_root("ak-flow-executor") prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor) prompt_stage.find_element( By.CSS_SELECTOR, "input[name=password]").send_keys(new_password) prompt_stage.find_element( By.CSS_SELECTOR, "input[name=password_repeat]").send_keys(new_password) prompt_stage.find_element(By.CSS_SELECTOR, "input[name=password_repeat]").send_keys( Keys.ENTER) self.wait_for_url(self.if_admin_url("/library")) # Because USER() is cached, we need to get the user manually here user = User.objects.get(username=USER().username) self.assertTrue(user.check_password(new_password))
def test_authorization_consent_implied(self): """test OpenID Provider flow (default authorization flow with implied consent)""" sleep(1) # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-implicit-consent" ) provider = OAuth2Provider.objects.create( name=self.application_slug, client_type=ClientTypes.CONFIDENTIAL, client_id=self.client_id, client_secret=self.client_secret, rsa_key=CertificateKeyPair.objects.first(), redirect_uris="http://localhost:9009/auth/callback", authorization_flow=authorization_flow, ) provider.property_mappings.set( ScopeMapping.objects.filter( scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE] ) ) provider.save() Application.objects.create( name=self.application_slug, slug=self.application_slug, provider=provider, ) self.container = self.setup_client() self.driver.get("http://localhost:9009") self.login() self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "pre"))) body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text) self.assertEqual(body["IDTokenClaims"]["nickname"], USER().username) self.assertEqual(body["UserInfo"]["nickname"], USER().username) self.assertEqual(body["IDTokenClaims"]["name"], USER().name) self.assertEqual(body["UserInfo"]["name"], USER().name) self.assertEqual(body["IDTokenClaims"]["email"], USER().email) self.assertEqual(body["UserInfo"]["email"], USER().email)
def test_authorization_consent_explicit(self): """test OAuth Provider flow (default authorization flow with explicit consent)""" # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-explicit-consent") provider = OAuth2Provider.objects.create( name="grafana", client_id=self.client_id, client_secret=self.client_secret, client_type=ClientTypes.CONFIDENTIAL, redirect_uris="http://localhost:3000/login/github", authorization_flow=authorization_flow, ) app = Application.objects.create( name="Grafana", slug="grafana", provider=provider, ) self.driver.get("http://localhost:3000") self.driver.find_element(By.CLASS_NAME, "btn-service--github").click() self.login() sleep(3) self.wait.until( ec.presence_of_element_located( (By.CSS_SELECTOR, "ak-flow-executor"))) flow_executor = self.get_shadow_root("ak-flow-executor") consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor) self.assertIn( app.name, consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text, ) self.assertEqual( "GitHub Compatibility: Access you Email addresses", consent_stage.find_element( By.CSS_SELECTOR, "[data-permission-code='user:email']").text, ) consent_stage.find_element( By.CSS_SELECTOR, ("[type=submit]"), ).click() self.wait_for_url("http://localhost:3000/?orgId=1") self.driver.get("http://localhost:3000/profile") self.assertEqual( self.driver.find_element(By.CLASS_NAME, "page-header__title").text, USER().username, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=name]").get_attribute("value"), USER().username, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=email]").get_attribute("value"), USER().email, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=login]").get_attribute("value"), USER().username, )
def test_authorization_consent_explicit(self): """test OpenID Provider flow (default authorization flow with explicit consent)""" sleep(1) # Bootstrap all needed objects authorization_flow = Flow.objects.get( slug="default-provider-authorization-explicit-consent") provider = OAuth2Provider.objects.create( name="grafana", authorization_flow=authorization_flow, client_type=ClientTypes.CONFIDENTIAL, client_id=self.client_id, client_secret=self.client_secret, rsa_key=CertificateKeyPair.objects.first(), redirect_uris="http://localhost:3000/login/generic_oauth", ) provider.property_mappings.set( ScopeMapping.objects.filter(scope_name__in=[ SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE ])) provider.save() app = Application.objects.create( name="Grafana", slug=APPLICATION_SLUG, provider=provider, ) self.driver.get("http://localhost:3000") self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click() self.login() self.wait.until( ec.presence_of_element_located( (By.CSS_SELECTOR, "ak-flow-executor"))) sleep(1) flow_executor = self.get_shadow_root("ak-flow-executor") consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor) self.assertIn( app.name, consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text, ) consent_stage.find_element( By.CSS_SELECTOR, ("[type=submit]"), ).click() self.wait_for_url("http://localhost:3000/?orgId=1") self.driver.get("http://localhost:3000/profile") self.assertEqual( self.driver.find_element(By.CLASS_NAME, "page-header__title").text, USER().name, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=name]").get_attribute("value"), USER().name, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=email]").get_attribute("value"), USER().email, ) self.assertEqual( self.driver.find_element( By.CSS_SELECTOR, "input[name=login]").get_attribute("value"), USER().email, )