Closed dnlopesoftware closed 1 year ago
@dnlopesoftware Does your code have silent auth enabled or checkAuth enabled ?
@DVGY There is not. I'm doing the token generation, using jwt decode and inserting it by locaStorage.
@dnlopesoftware I need to see the msal code + auth code. Also make sure that you have access to the APP or API in azure ad
I have access. The code is attachment in section. But follow the keys generated with post send with success;
@dnlopesoftware what does the msal code look like in you js files or jsx files?
1.check wether the keys stays in local storage.
Hi @DVGY , I'm using the file auth.js auth.js: ///
import { decode } from "jsonwebtoken"; import { jwt } from 'express-jwt'; import authSettings from "../fixtures/hlg/authSettings.json";
const { authority, clientId, clientSecret, apiScopes, username, password, } = authSettings; const environment = "login.windows.net";
const buildAccountEntity = ( homeAccountId, realm, localAccountId, username, name ) => { return { authorityType: "MSSTS", // This could be filled in but it involves a bit of custom base64 encoding // and would make this sample more complicated. // This value does not seem to get used, so we can leave it out. clientInfo: "", homeAccountId, environment, realm, localAccountId, username, name, }; };
const buildIdTokenEntity = (homeAccountId, idToken, realm) => { return { credentialType: "IdToken", homeAccountId, environment, clientId, secret: idToken, realm, }; };
const buildAccessTokenEntity = ( homeAccountId, accessToken, expiresIn, extExpiresIn, realm, scopes, tokentype ) => { const now = Math.floor(Date.now() / 1000); return { homeAccountId, credentialType: "AccessToken", secret: accessToken, cachedAt: now.toString(), expiresOn: (now + expiresIn).toString(), extendedExpiresOn: (now + extExpiresIn).toString(), environment, clientId, realm, target: "user.read.all, user.read, openid, profile, email", // Scopes must be lowercase or the token won't be found tokentype }; };
const buildAuthTokenEntity = ( aio, aud, email, exp, iat, iss, name, nbf, nonce, localAccountId, onpremisessamaccountname, username, rh, sub, realm, uti, ver ) =>{ return { aud: aud, aio: aio, email: email, exp: exp, iat: iat, iss: iss, name: name, nbf: nbf, nonce: nonce, oid: localAccountId, onpremisessamaccountname: onpremisessamaccountname, preferred_username: username, rh: rh, sub: sub, tid: realm, uti: uti, ver: ver } }
const buildpermProve = (access_token2, token_type2, expires_in2, scope2, grupos2, cargo2, jti2) =>{ return { access_token: access_token2, token_type: token_type2, expires_in: expires_in2, scope: scope2, grupos: grupos2, nivel: Object.keys(grupos2), cargo: cargo2, jti: jti2 } }
const injectTokens = (tokenResponse) => { const idToken = decode(tokenResponse.access_token); console.log(idToken) const localAccountId = idToken.oid || idToken.sid; const realm = idToken.tid; const homeAccountId = ${localAccountId}.${realm}; const username = idToken.preferred_username; const name = idToken.name; const tokentype = tokenResponse.token_type const aio = idToken.aio const aud = idToken.aud const email = idToken.upn const exp = idToken.exp const iat = idToken.iat const iss = idToken.iss const nbf = idToken.nbf const crypto = require('crypto');
function generateNonce() { return crypto.randomBytes(16).toString("hex"); } const nonce = generateNonce() const onpremisessamaccountname = "7700608017" const rh = idToken.rh const sub = idToken.sub const uti = idToken.uti const ver = idToken.ver
const proveAuthenticationTokenEntity = buildAuthTokenEntity( aio, aud, email, exp, iat, iss, name, nbf, nonce, localAccountId, onpremisessamaccountname, username, rh, sub, realm, uti, ver );
const accountKey = ${homeAccountId}-${environment}-${realm}; const accountEntity = buildAccountEntity( homeAccountId, realm, localAccountId, username, name );
const idTokenKey = ${homeAccountId}-${environment}-idtoken-${clientId}-${realm}-; const idTokenEntity = buildIdTokenEntity( homeAccountId, tokenResponse.access_token, realm );
const accessTokenKey = ${homeAccountId}-${environment}-accesstoken-${clientId}-${realm}-${apiScopes};
const accessTokenEntity = buildAccessTokenEntity( homeAccountId, tokenResponse.access_token, tokenResponse.expires_in, tokenResponse.ext_expires_in, realm, apiScopes, tokentype );
localStorage.setItem(accountKey, JSON.stringify(accountEntity)); localStorage.setItem(idTokenKey, JSON.stringify(idTokenEntity)); localStorage.setItem(accessTokenKey, JSON.stringify(accessTokenEntity)); localStorage.setItem("proveAuthenticationToken", JSON.stringify(proveAuthenticationTokenEntity)); };
const injectTokensProve = (tokenResponse) => { const access_token2 = tokenResponse.access_token; const token_type2 = tokenResponse.token_type; const expires_in2 = tokenResponse.expires_in; const scope2 = tokenResponse.scope; const grupos2 = tokenResponse.grupos; const cargo2 = tokenResponse.cargo; const jti2 = tokenResponse.jti;
const provePermissaoToken = buildpermProve( access_token2, token_type2, expires_in2, scope2, grupos2, cargo2, jti2);
localStorage.setItem("provePermissaoToken",JSON.stringify(provePermissaoToken)); }
export const login = (cachedTokenResponse) => { let tokenResponse1 = null; let tokenResponse2 = null; let chainable = cy.visit("/"); //let chainableProve = cy.visit("/");
if (!cachedTokenResponse) { chainable = chainable.request({ url: authority + "/oauth2/v2.0/token", method: "POST", body: { grant_type: "password", client_id: clientId, client_secret: clientSecret, scope: apiScopes, username: username, password: password, }, form: true, }); } else { chainable = chainable.then(() => { return { body: cachedTokenResponse, }; }); }
chainable.then((response) => { console.log(response.body) injectTokens(response.body); tokenResponse1 = response.body; }).then(() => { let chainable = null; });
if(chainable){ chainable = chainable.request({ url: "https://xxxx/oauth/token", method: "POST", auth: { username: "", password: "" }, form: true, body: { grant_type: "password", scope: "read+write", username: "", password: "" } }) }
chainable.then((response2) => { console.log(response2.body) injectTokensProve(response2.body); tokenResponse2 = response2.body; }).then(() => { return tokenResponse1; });
return chainable; };
@dnlopesoftware This is test code, I want to see what really happens in the front end when someone logs in, Instead of doing reload try visiting some URL.
If the issue still persist, you can check out my blog post: https://dev.to/kauppfbi_96/test-msal-based-spas-with-cypress-4goe
It also follows the same approach, but maybe you find the missing piece.
Also MSAL triggers a Redirect when you initially acquired a token without requesting all necessary scopes. If you later try to use a API with a specific scope required, the login flow is triggered again.
I'm also experiencing this with Azure B2C Login, I've tried with Origin and Session but still get the same issue constantly.
This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.
This issue has been closed due to inactivity.
Current behavior
I'm having a problem using azure AD authentication. I'm using the same model provided by Joonas Westlin(https://github.com/juunas11/AzureAdUiTestAutomation); All keys and locastorages are being generated as expected by my application, but after cy.reload I am redirected to the screen "https://login.microsoftonline.com/" to inform the username and password.
Does cypress already have another solution for interacting with AD Azure?
Desired behavior
No response
Test code to reproduce
auth.js: ///
import { decode } from "jsonwebtoken"; import { jwt } from 'express-jwt'; import authSettings from "../fixtures/hlg/authSettings.json";
const { authority, clientId, clientSecret, apiScopes, username, password, } = authSettings; const environment = "login.windows.net";
const buildAccountEntity = ( homeAccountId, realm, localAccountId, username, name ) => { return { authorityType: "MSSTS", // This could be filled in but it involves a bit of custom base64 encoding // and would make this sample more complicated. // This value does not seem to get used, so we can leave it out. clientInfo: "", homeAccountId, environment, realm, localAccountId, username, name, }; };
const buildIdTokenEntity = (homeAccountId, idToken, realm) => { return { credentialType: "IdToken", homeAccountId, environment, clientId, secret: idToken, realm, }; };
const buildAccessTokenEntity = ( homeAccountId, accessToken, expiresIn, extExpiresIn, realm, scopes, tokentype ) => { const now = Math.floor(Date.now() / 1000); return { homeAccountId, credentialType: "AccessToken", secret: accessToken, cachedAt: now.toString(), expiresOn: (now + expiresIn).toString(), extendedExpiresOn: (now + extExpiresIn).toString(), environment, clientId, realm, target: "user.read.all, user.read, openid, profile, email", // Scopes must be lowercase or the token won't be found tokentype }; };
const buildAuthTokenEntity = ( aio, aud, email, exp, iat, iss, name, nbf, nonce, localAccountId, onpremisessamaccountname, username, rh, sub, realm, uti, ver ) =>{ return { aud: aud, aio: aio, email: email, exp: exp, iat: iat, iss: iss, name: name, nbf: nbf, nonce: nonce, oid: localAccountId, onpremisessamaccountname: onpremisessamaccountname, preferred_username: username, rh: rh, sub: sub, tid: realm, uti: uti, ver: ver } }
const buildpermProve = (access_token2, token_type2, expires_in2, scope2, grupos2, cargo2, jti2) =>{ return { access_token: access_token2, token_type: token_type2, expires_in: expires_in2, scope: scope2, grupos: grupos2, nivel: Object.keys(grupos2), cargo: cargo2, jti: jti2 } }
const injectTokens = (tokenResponse) => { const idToken = decode(tokenResponse.access_token); console.log(idToken) const localAccountId = idToken.oid || idToken.sid; const realm = idToken.tid; const homeAccountId =
${localAccountId}.${realm}
; const username = idToken.preferred_username; const name = idToken.name; const tokentype = tokenResponse.token_type const aio = idToken.aio const aud = idToken.aud const email = idToken.upn const exp = idToken.exp const iat = idToken.iat const iss = idToken.iss const nbf = idToken.nbf const crypto = require('crypto');function generateNonce() { return crypto.randomBytes(16).toString("hex"); } const nonce = generateNonce() const onpremisessamaccountname = "7700608017" const rh = idToken.rh const sub = idToken.sub const uti = idToken.uti const ver = idToken.ver
const proveAuthenticationTokenEntity = buildAuthTokenEntity( aio, aud, email, exp, iat, iss, name, nbf, nonce, localAccountId, onpremisessamaccountname, username, rh, sub, realm, uti, ver );
const accountKey =
${homeAccountId}-${environment}-${realm}
; const accountEntity = buildAccountEntity( homeAccountId, realm, localAccountId, username, name );const idTokenKey =
${homeAccountId}-${environment}-idtoken-${clientId}-${realm}-
; const idTokenEntity = buildIdTokenEntity( homeAccountId, tokenResponse.access_token, realm );const accessTokenKey =
${homeAccountId}-${environment}-accesstoken-${clientId}-${realm}-${apiScopes}
;const accessTokenEntity = buildAccessTokenEntity( homeAccountId, tokenResponse.access_token, tokenResponse.expires_in, tokenResponse.ext_expires_in, realm, apiScopes, tokentype );
localStorage.setItem(accountKey, JSON.stringify(accountEntity)); localStorage.setItem(idTokenKey, JSON.stringify(idTokenEntity)); localStorage.setItem(accessTokenKey, JSON.stringify(accessTokenEntity)); localStorage.setItem("proveAuthenticationToken", JSON.stringify(proveAuthenticationTokenEntity)); };
const injectTokensProve = (tokenResponse) => { const access_token2 = tokenResponse.access_token; const token_type2 = tokenResponse.token_type; const expires_in2 = tokenResponse.expires_in; const scope2 = tokenResponse.scope; const grupos2 = tokenResponse.grupos; const cargo2 = tokenResponse.cargo; const jti2 = tokenResponse.jti;
const provePermissaoToken = buildpermProve( access_token2, token_type2, expires_in2, scope2, grupos2, cargo2, jti2);
}
export const login = (cachedTokenResponse) => { let tokenResponse1 = null; let tokenResponse2 = null; let chainable = cy.visit("/"); //let chainableProve = cy.visit("/");
if (!cachedTokenResponse) { chainable = chainable.request({ url: authority + "/oauth2/v2.0/token", method: "POST", body: { grant_type: "password", client_id: clientId, client_secret: clientSecret, scope: apiScopes, username: username, password: password, }, form: true, }); } else { chainable = chainable.then(() => { return { body: cachedTokenResponse, }; }); }
chainable.then((response) => { console.log(response.body) injectTokens(response.body); tokenResponse1 = response.body; }).then(() => {
let chainable = null; });
if(chainable){ chainable = chainable.request({ url: "https://xxxx/oauth/token", method: "POST", auth: { username: "", password: "" }, form: true, body: { grant_type: "password", scope: "read+write", username: "", password: "" } }) }
chainable.then((response2) => { console.log(response2.body) injectTokensProve(response2.body); tokenResponse2 = response2.body; }).then(() => {
return tokenResponse1; });
return chainable; };
Commands.js: import { login } from "./auth";
let cachedTokenExpiryTime = new Date().getTime(); let cachedTokenResponse = null;
Cypress.Commands.add( 'loginProve', (enderecoAcesso) => { // Clear our cache if tokens are expired if (cachedTokenExpiryTime <= new Date().getTime()) { cachedTokenResponse = null; }
} )
Cypress Version
7.6.0
Other
No response