Due to a lack of knowledge in JS, I do face with below problem.
I do automation testing with cypress and for external API endpoints, I need to use Dynamic Token that expires every 3600 secs.
I did some short research and find out that, for reaching to JWT Token I will need 1st SSO login (that my app has). Then use the below script.
But I don't know what to do after this.
it('the value of JWT Token should exist in localStorage', () => {
cy.getLocalStorage('JWT_DATA').then(lsData => {
cy.log('the token', lsData); // I get JWT Token in here
});
});
The result of this script is only printing the TOKEN.
But I need to store it somehow and then be able to reuse it for every different API endpoint call.
You can use Cypress.env for this. Then you can use the token throughout the test anywhere.
it('the value of JWT Token should exist in localStorage', () => {
cy.getLocalStorage('JWT_DATA').then((lsData) => {
cy.log('the token', lsData) // I get JWT Token in here
Cypress.env('token', lsData)
})
})
To use it, you can do
Cypress.env('token')
Related
I'm trying to use msalv2 js library to do SSO authentication. It mostly works but I find an issue with token expiring and how to renew it.
I am calling the aquireTokenRedirect function to get the new token and auto renew it but I see that it keeps returning the same token. I try to auto renew it when my server side code detects that the token is expired. It uses a msal jwt library to check.
My guess as to what is happening is, my app is sending the id token to the server (I use that instead of access token), and the server decodes it and sees the exp value, which is the ExpiresOn value from the msal js response.
When this time has expired, it will return a 401 error which is fine. However then I try to renew it on the client side, but find it gives me back the same token value...
I check the msal response from earlier and notice there is a extExpiresOn value which is a little later in time. So now i'm thinking the msal library only renews on this time.
So the question is, how can I configure msalv2 js library to renew on the ExpiresOn instead of the extExpiresOn?
Thanks
function getTokenRedirect(request) {
/**
* See here for more info on account retrieval:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/Accounts.md
*/
request.account = myMSALObj.getAccountByUsername(username);
return myMSALObj.acquireTokenSilent(request)
.catch(error => {
console.warn("silent token acquisition fails. acquiring token using redirect");
if (error instanceof msal.InteractionRequiredAuthError) {
// fallback to interaction when silent call fails
return myMSALObj.acquireTokenRedirect(request);
} else {
console.warn(error);
}
});
}
I would really like to expand on this topic "Logging in with CSRF token" as I have been banging my head against a wall for weeks now and I can't be the only one with this problem. All topics about logging in via POST or logging in with CSRF inevitably lead back to the above link.
Yet the recipes described in this link do not seem to work for me. They all assume that the CSRF token is created once you visit the Login page. But on our site, the CSRF token is only created once you login.
I tested with Postman and there is no CSRF token in the HTML or in the header before you are logged in.
I also tested it in Cypress with the following code:
describe('gimme dat csrf token', () => {
it('try to get the csrf token', () => {
cy.visit(Cypress.env('url'))
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
This will return an error as there is no YII_CSRF_TOKEN
Type Error
Cannot read properties of null (reading 'value')
If I add a login step before, it will return the value of the CSRF token as expected:
import {Login} from "../../pages/login/Login";
describe('gimme dat csrf token', () => {
it('try to get csrf token', () => {
cy.visit(Cypress.env('url'))
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass')) //added login
cy.getCookie('YII_CSRF_TOKEN')
.then(async (c) => {
cy.log(c.value)
return c.value
})
})
})
Therefore strategies #1 (parse token from HTML) and #2 (parse token from response headers) from the above link can not work.
Recipe #3 is also not feasible as we have several live systems to test and we can't expose a /csrf route
This only leaves us with the strategy #4, which we have been using so far.
Any ideas or are we stuck with adding the "manual" login step to every single spec file?
I think strategies #1 & #2 rely on the browser remembering credentials and supplying them to the login page, as happens with the Stackoverflow page - you don't have to log in every time you visit.
The main difference is you have used cy.visit() instead of cy.request() as shown in the recipes.
If you still are not able to successfully grab the token, try using your login with cy.session(). It will only call the login function once per session.
/*
Enable use of cy.session() and new behavior to handle caching
and restoring cookies, localStorage, and sessionStorage.
*/
Cypress.config('experimentalSessionSupport', true)
describe('...', () => {
beforeEach(() => {
cy.session(() => {
login.loginCredentials(Cypress.env('userEmail'), Cypress.env('userPass'))
})
})
it('try to get csrf token', () => {
cy.getCookie('YII_CSRF_TOKEN')
.then((c) => {
cy.log(c.value)
})
})
})
I have implemented the signin method using Firebase Auth for several providers like that:
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
let provider = new firebase.auth.GoogleAuthProvider(); // + facebook, gitHub
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(result => {
// app logic here
However this code gives me 60 min lasting sessions and I want to learn how to automatically renew the current user session without being forced to login every hour.
I'm also 'listening' to the current user session state using this code.
firebase.auth().onAuthStateChanged(user => if (!user) //goto LoginPage
But it doesn't 'listen' per se, it works only when I try to navigate or update the page. So I don't know how to restrict access by the exact amount of time (e.g. 15 minutes max) using Firebase methods.
The documentation says there is a getIdToken method but I can't wrap my head around where to use this code. Should it be invoked every 60 minutes just before the expiration or it should be set at the time of login? Please give some hints or any tutorials covering this very situation.
EDIT:
Also I get this code in the console after some period of inactivity (I think less than 1 hour):
auth.esm.js:121 POST https://securetoken.googleapis.com/v1/token?key=AIza... 403
Firebase tokens are set to expire after 60 min. Then it gets refreshed for you automatically. There is no way to configure the expiration time, and you don't need to do anything special in your front-end code for that.
The only trick is that, you need to grant your application API key the permission to use the Token Service API to be able to mint a new id token for you once it's expired. This is done in the GCP console, API & Services (Credentials).
So, the code should be simple as the following
Add the user authentication state change Listener
fbAuth.onAuthStateChanged(user => {
if (user) {
// User is logged in
// Proceed with your logged in user logic
} else {
// USer is not logged in
// Redirect to the login page
}
})
Implement the login logic
fbAuth.setPersistence(firebase.auth.Auth.Persistence.LOCAL)
.then(() => {
return fbAuth.signInWithEmailAndPassword(email, password)
.then(userCredential => {
// Login success path
})
.catch(error => {
// Login error path
});
})
.catch(error => {
// Persistence setting error path
})
You can set the Authentication State Persistence before the login, depending on your use cases auth-state-persistence.
Make sure that your application API key has access to the Token Service API in the GCP console
This is under
GCP Console | APIs & Services | Credentials
Then edit the corresponding key to your deployment environment to grant the API key the access to the Token Service API.
Good luck ;)
Hello first I am gonna say sorry fro my bad english. I dont really understand firebase but i think it should work if you write something like this:
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION).then(() => {
let provider = new firebase.auth.GoogleAuthProvider(); // + facebook, gitHub
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(result => {
// app logic here
I meant that you should have firebase.auth.Auth.Persistence.SESSION insted of LOCAL
I am using AWS API gateway for API's and cognito UserPool's for security. After Authenticating the user we will get tokens and I am using that token to authorise my API.
Now, I am trying to enable signout to cognito authorised users using javascript. Used the below code.
if (cognitoUser != null) {
cognitoUser.globalSignOut({
onFailure: e => console.log(e),
onSuccess: r =>
console.log('Logout success: ' + r)
})}
I am getting response as success but still I am able to access my API with the previous tokens.Please suggest me how to inactivate all the tokens issued to that cognito user.
The id token, which API Gateway uses to authenticate API calls, stays valid for a while.
I would test for the access token. It should expire right after you call global sign out.
The key word is should above. Please see this issue. It’s an on-going struggle to get AWS to implement an immediate revocation. Here’s a relevant quote:
I worked with AWS Cognito team to get this taken care and got released as a fix through CLI as following.
aws cognito-identity update-identity-pool --identity-pool-id --identity-pool-name --allow-unauthenticated-identities --cognito-identity-providers ProviderName=,ClientId=,ServerSideTokenCheck=<true|false>
By setting the ServerSideTokenCheck to true on a Cognito Identity
Pool, that Identity Pool will check with Cognito User Pools to make
sure that the user has not been globally signed out or deleted before
the Identity Pool provides an OIDC token or AWS credentials for the
user. Now we are running into another issue of this Token being cached
in API Gateway for 10mins which would let that OID token still be
active for 10mins even though the User has globally signed out.
Here's what I mean by test for the accessToken (I have had success with method #2):
1.) you could develop a custom authorizer for API Gateway;
2.) you could perform a check at the start of your lambda functions or on your servers, using:
const AWS = require('aws-sdk');
const awsConfig = require('./awsConfig');
const cognito = new AWS.CognitoIdentityServiceProvider(awsConfig);
// accessToken provided from API Gateway
new Promise((resolve, reject) => {
cognito.getUser({ accessToken }, (errorCallback, response) => {
if (errorCallback) {
reject(errorCallback);
} else {
resolve(response);
}
});
});
The errorCallback and response do not matter. If you get an error, the token is invalid. If you don’t, it’s valid.
I am using this method to decode token and get expiry of token,
var decode = Msal.IdToken(localStorage["msal.idtoken"]);
I use this because I want to avoid add one more jwtdecode library of angularJS.
We use MSAL for Active directory login functionality.
I've only been able to get a hold of the id token one of two ways using MSAL v.0.1.3.
The first was directly from sessionStorage:
let idtoken = sessionStorage.getItem("msal.idtoken")
The second was to store it upon successful login:
let idToken = "";
msalClient.loginPopup("myclientid",null)
.then(token => {
idToken = token;
});
The problem is that neither of these methods deals with token expiration -- but I haven't found anything in the MSAL library that will return the current id token.