-
-
Save ndavis/2c84ab40aaa3c98c3a8062bdb3938232 to your computer and use it in GitHub Desktop.
Cypress.Commands.add('loginOkta', () => { | |
const optionsSessionToken = { | |
method: 'POST', | |
url: Cypress.env('session_token_url'), | |
body: { | |
username: Cypress.env('username'), | |
password: Cypress.env('password'), | |
options: { | |
warnBeforePasswordExpired: 'true' | |
} | |
} | |
} | |
cy.request(optionsSessionToken).then(response => { | |
const sessionToken = response.body.sessionToken; | |
const qs = { | |
client_id: Cypress.env('client_id'), | |
code_challenge: Cypress.env('code_challenge'), | |
state: Cypress.env('state'), | |
nonce: Cypress.env('nonce'), | |
redirect_uri: Cypress.env('redirect_uri'), | |
code_challenge_method: 'S256', | |
response_mode: 'fragment', | |
response_type: 'code', | |
scope: ['openid', 'profile', 'email'], | |
sessionToken: sessionToken | |
} | |
cy.request({ | |
method: 'GET', | |
url: Cypress.env('auth_token_url'), | |
form: true, | |
followRedirect: false, | |
qs: qs | |
}).then(responseWithToken => { | |
const redirectUrl = responseWithToken.redirectedToUrl; | |
const accessToken = redirectUrl | |
.substring(redirectUrl.indexOf('access_token')) | |
.split('=')[1] | |
.split('&')[0]; | |
cy.wrap(accessToken).as('accessToken'); | |
cy.visit(redirectUrl).then(() => { | |
cy.visit('/'); | |
}); | |
}); | |
}); | |
}) |
Great stuff! Thank you for the refactoring and making the code nicer :)
It works pretty well.
In our case, we had to remove the last cy.visit("/"), since it was not been understood properly by Cypress.
It because you probably didn't set baseUrl of your app in cypress.json.
https://docs.cypress.io/guides/references/configuration.html#Global
Thanks, that's was the issue.
It is working now.
awesome! worked for me. Was able to comment out
// code_challenge: Cypress.env('code_challenge'),
// state: Cypress.env('state'),
// nonce: Cypress.env('nonce'),
and it still worked.
Yes, code_challenge was not required for me either
By the way, I am trying to implement a similar command for the logout function.
It is basically the same code as for login, but changing parameters (according to Okta documentation) and the url.
This is the code I have done so far:
Cypress.Commands.add('logoutOkta', () => {
var redirect_uri = "" + Cypress.env('testConfig').baseUrl + Cypress.env('redirect_uri');
cy.log(redirect_uri);
const sessionToken = Cypress.env('accessToken');
cy.log(sessionToken);
const qs = {
id_token_hint: sessionToken,
post_logout_redirect_uri: `${Cypress.env('testConfig').baseUrl}/Account/Logout`,
state: Cypress.env('state')
}
cy.request({
method: 'GET',
url: Cypress.env('auth_logout_url'),
form: true,
followRedirect: false,
qs: qs
}).then(responseWithToken => {
const redirectUrl = responseWithToken.redirectedToUrl;
cy.visit(redirectUrl).then(() => {
cy.visit('/');
});
});
});
It returns 302, but when accessing the url in the browser, a page appears showing the following error message:
400: Bad Request
BAD REQUESTYour request resulted in an error.
Go to Homepage
Identity Provider:
Error Code: invalid_token
Description: The id token is invalid.
Has anyone tried implementing Logout?
Does anyone know if someone's adapted this or similar for Auth0 PKCE?
Does anyone know if someone's adapted this or similar for Auth0 PKCE?
@DaveA-W See if https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/ can help you.
Does anyone know if someone's adapted this or similar for Auth0 PKCE?
@DaveA-W See if https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/ can help you.
Thanks @khitrenovich - unfortunately that article demonstrates password grant only.
Only potential workaround I've seen so far is not ideal, per corruptedmonk comments at the bottom of the article:
- Disable chrome security in Cypress config.
- Use Classic universal login.
- Disable click-jacking protection in advanced tenant settings.
Then Cypress may handle the redirects and silent auth okay - but at the expense of compromising security for the whole tenant.
Hello, this code snippet works fine when I was using Okta v2, but now after I upgrade to Okta v3, it causes AuthSdkError: Unable to parse a token from the url
. Does anyone know how to handle this in Okta v3? Thanks a lot.
I am facing the same SSO login issue. My application uses OpenID as auth server.
will this approach solve the login issue for OpenID?
Hi ,
Im also facing the "AuthSdkError: Unable to retrieve OAuth redirect params cookie" . any help would really appreciate.
Every time I rerun the test in the same browser it gives me this error. But If I start a fresh test it doesnt give me error. I guess for second test attempt its not able to find the cookie or etc I suspect. But unable to resolve the solution.
Below is my OKTA code.
`Cypress.Commands.add('loginOkta', () => {
const optionsSessionToken = {
method: 'POST',
url: Cypress.env('session_token_url'),
body: {
username: Cypress.env('username'),
password: Cypress.env('password'),
options: {
warnBeforePasswordExpired: 'true'
}
}
}
cy.request(optionsSessionToken).then(response => {
const sessionToken = response.body.sessionToken;
const qs = {
client_id: Cypress.env('client_id'),
//code_challenge: Cypress.env('code_challenge'),
//state: Cypress.env('state'),
//nonce: Cypress.env('nonce'),
redirect_uri: Cypress.env('redirect_uri'),
code_challenge_method: 'S256',
response_mode: 'fragment',
response_type: 'code',
scope: ['openid', 'profile', 'email'],
sessionToken: sessionToken
}
cy.request({
method: 'GET',
url: Cypress.env('auth_token_url'),
form: true,
followRedirect: false,
qs: qs
}).then(responseWithToken => {
const redirectUrl = responseWithToken.redirectedToUrl;
const accessToken = redirectUrl
.substring(redirectUrl.indexOf('access_token'))
.split('=')[1]
.split('&')[0];
cy.wrap(accessToken).as('accessToken');
cy.visit(redirectUrl).then(() => {
cy.visit('/');
});
});
});
});`
below is my test:
before('Open the atmos', () => {
console.log('inside the before', " user name -");
cy.loginOkta();
})
it('login to atmos via okta', () => {
console.log('inside the beffore', " user name -");
// cy.loginOkta();
})
it('Click create team', () => {
cy.get(':nth-child(2) > a > .card > .card-body > .clearcard-title').click()
})`
-Hemant
just an update.
I was able to resolve my issue by following original code
cypress-io/cypress#4416 (comment)
If I re-run the test from the browser, I dont see the error. Atlest my test continues each time.
Not sure why. But i thought this might help anyone.
In my solution chrome is giving me sameSite error. Does anyone faced this issue?
Even though okta login successful Im keep seeing the okta login screen and if I open need tab in same session Im able to access my app.
Its kinda confusing that one tabshows okta login and another tab shows successful login.
It was working earlier chrome version less than 80.
Hi there
That workaround also started failing for me since last week. I haven't been able to find a reason why it stopped working.
The flow is slightly different as the solution provided by @ndavis
- Get a session token (same as before)
- Use the library okta-auth-js (npm i @okta/okta-auth-js) calling the method getWithoutPrompt to get the idToken and set the variable into the Okta authClient object.
var OktaAuth = require('@okta/okta-auth-js');
var authClient = new OktaAuth({
url: 'https://YOUR_DOMAIN.okta.com',
clientId: Cypress.env('client_id'),
redirectUri: Cypress.env('testConfig').baseUrl + Cypress.env('redirect_uri')
});
// Attempt to retrieve ID Token from Token Manager
const optionsSessionToken = {
method: 'POST',
url: Cypress.env('session_token_url'),
body: {
username: username,
password: password,
options: {
warnBeforePasswordExpired: 'true'
}
}
}
var redirect_uri = "" + Cypress.env('testConfig').baseUrl + Cypress.env('redirect_uri');
cy.log(redirect_uri);
cy.request(optionsSessionToken).then(response => {
const sessionToken = response.body.sessionToken;
authClient.token.getWithoutPrompt({
sessionToken: sessionToken,
scopes: [
'openid',
'email',
'profile'
],
state: Cypress.env('state'),
nonce: Cypress.env('nonce')
})
.then(function (res) {
authClient.tokenManager.add('idToken', res);
})
.catch(function (err) {
// handle OAuthError or AuthSdkError
});
})
cy.visit('/')
I thought this was going to solve the issue in Firefox as well since it should be crossing domains; however, I am still getting the same error in Firefox as I was getting before.
Hope it helps.
Hi @cuadllop ! Did you decide this problem?
Maybe you may tell me where I get these options ?
- code_challenge
- nonce
- state
Reviewed in all requests in authorization in okta and never came....
Hi @boda234baran,
Yes, this solution is working for me and my team so far.
I got those details by analyzing the POST requests when doing a manual login into my app:
Bear in mind that each environment you have configured in okta will have its own set of properties.
Then it is configured in my env.json properties file
, I don't know the value of code_challenge. It works for me to configure it as empty
"code_challenge": "",
Hi, I am newbie to cypress, how can I integrate this code for okta authentication into my existing tests on Cypress?
Thank you
Here is the solution that worked for me. Two things to point out:
- Your company might be using custom
OKTA_AUTHORIZATION_SERVER_ID
and notdefault
that is used in the most doc examples - You should be able to use dummy values for
state
andnonce
Certain values (like scope
) might be different for your Okta configuration, but you should be able to identify them by inspecting the network tab.
Cypress.Commands.add('oktaApiLogin', ({ email, password, url }) => {
const optionsSessionToken = {
method: 'POST',
url: `${Cypress.env('OKTA_DOMAIN')}/api/v1/authn`,
body: {
username: email,
password,
options: {
warnBeforePasswordExpired: 'true',
},
},
};
cy.request(optionsSessionToken).then((response) => {
const { sessionToken } = response.body;
cy.log(`sessionToken: ${sessionToken}`);
const qs = {
response_type: 'code',
client_id: Cypress.env('OKTA_CLIENT_ID'),
state: 'test-state',
nonce: 'test-nonce',
redirect_uri: Cypress.env('OKTA_REDIRECT_URI'),
scope: 'openid offline_access email',
sessionToken,
};
cy.request({
method: 'GET',
url: `${Cypress.env('OKTA_DOMAIN')}/oauth2/${Cypress.env(
'OKTA_AUTHORIZATION_SERVER_ID'
)}/v1/authorize`,
form: true,
followRedirect: false,
qs,
}).then((responseWithToken) => {
const redirectUrl = responseWithToken.redirectedToUrl;
cy.log('responseWithToken:', responseWithToken);
cy.log('redirectUrl:', redirectUrl);
cy.request({
method: 'GET',
url: redirectUrl,
followRedirect: false,
});
cy.visit(url);
});
});
});
Okta supports hosting a sign-in page under your own domain with Embedded Okta Sign-In Widget. In this way, since you use your domain, cypress work seamlessly.
Okta provides a sign-in page, available at your organization's URL, which allows the user to complete the entire authorization flow, start an SSO (Single Sign-On) session, and set the Okta session cookie in the web browser. You can customize this page with a background image and logo. By default, signing in on this page redirects the user to the Okta user dashboard.
See the GitHub repository for the implementation
PS: Use the embed link, so the login process ends with the application you want to test instead of Okta dashboard.
Edit:
Important update: Cypress has introduced cy.origin()
command with version 9.6.0 that allows you to visit multiple origins in a single test. See here for details.
Hey I'm getting this error when running tests/
cy.request() requires a url. You did not provide a url
Should optionsSessionToken
have a url in it to provide?
@iamskok hi, is there any example to test if there is MFA enable in okta, In my app we have enabled the okta sms MFA.
Hi, i´m newbie in cypress. how to implement Okta DSSO (Desktop single sign-on) authentication using cypress? with DSSO there is no prompt page to enter user/password for authentication, seems that okta does the authentication in the background when i login into the computer. Since cypress use its own browser to run the automation when it hits the app URL i´m getting an error message saying the i´m not allowed to processed since i´m not authenticated. Please help.
Thanks in advance
Credit to @Postavshik
Import Custom Command
In
commands.js
import the file like so:Setup Environment Variables
Set up a
cypress.env.json
with variables defined in thecommands.js
:For
session_token_url
replace the <...> with your okta domainFor
auth_token_url
replace the <...> with your okta domainGet Additional Environment Variable from Browser
If you sign into Okta in your browser and inspect the
default/v1/authorize
network call you'll be able to find these values: