Starting cypress ui test between (20..30) or (50..60) second of the minute causes wrong Google 2 factor token generation. It generates prevoious token.
Here is my token generation function:
function getToken () {
const totp = require('totp-generator');
const token = totp('2CQQGPPYFE7JPJAX');
return token;
}
Here is how i get token before using it:
let token = getToken()
It looks like the token is generated on the beginning of the test (even if the call is in the middle of the test), and token is outdated at the time of it's usage, because new period has started.
Avoid hard waits
I would use an element on the page instead of a millisecond wait.
describe('check the tokens', function()
{
// First test
it('cy.window() - get the global window object', () => { cy.viewport(500, 780)
cy.visit('https://site.domain',)
cy.get('input[name=email]').type('email#server.io')
cy.get('input[name=password]').focus().type('qwerty123')
cy.get('.Button').click()
// Now lets wait on an object that appears on the page
// when ready to input the token
cy.get(<someElement>).then(()=>{
let token = getToken();
console.log('first token: ' + token);
})
})
//Second test
it('cy.window() - get the global window object', () => { cy.viewport(500, 780)
cy.visit('https://site.domain',)
cy.get('input[name=email]').type('email#server.io')
cy.get('input[name=password]').focus().type('qwerty123')
cy.get('.Button').click()
// Now lets wait on an object that appears on the page
// when ready to input the token
cy.get(<someOtherElement>).then(()=>{
let token = getToken();
console.log('second token: '+ token);
});
})
})
function getToken () {
const totp = require('totp-generator');
const token = totp('2CQQGPPYFE7JPJAX');
return token;
}
More advanced
Even better than waiting on an element would be waiting on a network event or method to be called... https://docs.cypress.io/api/commands/wait.html#Alias
Does this work for you?
Use promise function.
describe('check the tokens', function()
{
// on 25 seconds
it('Test first token ',()=> {
cy.wait(25000).then(()=>{
let token = getToken();
console.log('first token: ' + token);
})
})
// on 55 seconds
it('Test second token', ()=>{
cy.wait(30000).then(()=>{
let token = getToken();
console.log('second token: '+ token);
});
})
})
function getToken () {
const totp = require('totp-generator');
const token = totp('2CQQGPPYFE7JPJAX');
return token;
}
Related
I have a function which generates a refresh token.
async refreshToken(token: string): Promise<{ token: string } | ErrorDetails> {
if (!token)
throw new HttpException('No token provided', HttpStatus.BAD_REQUEST)
token = token.split(' ')[1]
const jwtToken = await this.jwtService
.verifyAsync(token, {
secret: process.env.JWT_SECRET,
})
.catch((error) => {
if (error === 'jwt expired') return
})
// Here if token is expired jwtToken is null
if (!jwtToken)
throw new HttpException('Invalid token', HttpStatus.FORBIDDEN)
const user = await this.userService.findUserByAllFields(jwtToken.user)
if (!user) throw new HttpException('Invalid token', HttpStatus.FORBIDDEN)
const userDetails = this.userService._getUserDetails(jwtToken.user)
const jwt = await this.jwtService.signAsync({ userDetails })
return { token: jwt }
}
I wan't to check if the token is right but without checking the expiration
Is there any way to handle it ?
this.jwtService.verify(token, {
secret,
ignoreExpiration: true,
});
If you don't pass expireIn option or exp claim there will not be any exp claim, so the JWT does not have any expiration.
I'm setting Token in localstorage and send it to every request with (axios), but the problem is when I use getServerSideProps token is not send because localStorage can't be accessed on server side.
I think I should use Cookies, I tried js-cookies but it didn't work on server as well.
Is there any solution to send token on server side fetching function as getServerSideProps and getStaticProps?
Localstorage is client-side only; use getInitialProps
function Page({ stars }) {
return <div>Next stars: {stars}</div>
}
Page.getInitialProps = async ({ req }) => {
let token;
// server
if (req) return { page: {} };
else {
// client
const token = localStorage.getItem("auth");
const res = await fetch('https://api.github.com/repos/vercel/next.js', { headers: { Authorization: token }});
const data = await res.json();
return { page: data };
}
};
export default Page
Just modify my code, normally it works
I have pages with connexion and deconnexion to login on my nuxt app.
I use Symfony for the back and the librairy JWT for token authentification.
Here this is the code auth.js called when an user is login on my app. This works but I would like to store in my vuex the data into the token (I have the role and I would like to use it to display different things on page in function of the role). How can I do this ? Thanks for help
import axios from "axios";
import jwtDecode from "jwt-decode";
export const login = async (data) => {
const token = await axios
.post(process.env.baseUrl + 'login_check', data)
.then (response => response.data.token )
window.localStorage.setItem("authToken", token)
axios.defaults.headers["Authorization"] = "Bearer " + token;
}
export const logout = () => {
window.localStorage.removeItem("authToken")
delete axios.defaults.headers['Authorization'];
}
export const verifToken = () => {
const token = window.localStorage.getItem("authToken");
if (token ) {
const jwtData = jwtDecode(token);
if (jwtData.exp * 1000 > new Date().getTime()) //
{
axios.defaults.headers["Authorization"] = "Bearer " + token;
//console.log("connexion axios OK")
return true
}
else // if expired
{
logout();
}
}
//if no token
else {
logout();
console.log("no token")
}
}
I am using axios interceptors to check auth token on every request. This works fine. But when accessToken is null getToken() is fired twice. Is there a way to wait for the getToken to finish ? I just want getToken to fire once. The other requests needing a token should wait until getToken is fulfilled.
let isAlreadyFetchingAccessTokenRequest = false;
api.interceptors.request.use(
async config => {
let token = window.localStorage.getItem("accessToken");
if (!isAlreadyFetchingAccessTokenRequest && !token) {
isAlreadyFetchingAccessTokenRequest = true;
token = await getToken();
console.log("1. save token to local storage", token);
window.localStorage.setItem("accessToken", token);
}
config.headers.Authorization = `Bearer ${token}`;
return config;
},
function(error) {
return Promise.reject(error);
}
);
You are able to await a promise multiple times.
So could try something like this
let tokenPromise = null;
api.interceptors.request.use(
async config => {
let token = window.localStorage.getItem("accessToken");
if (!token) {
if (!tokenPromise) {
tokenPromise = getToken();
}
token = await tokenPromise;
console.log("1. save token to local storage", token);
window.localStorage.setItem("accessToken", token);
}
config.headers.Authorization = `Bearer ${token}`;
...
I'd like to get the auth token from firebase (email and password auth) to authenticate in my firebase cloud function. It seems like the functions getIdToken() and getToken() are both not working for firebase_auth package.
is there an other function or is there even a better idea to make sure only authenticated users can trigger the cloud functions?
var token = await FirebaseAuth.instance.currentUser.getIdToken();
var response = await httpClient.get(url,headers: {'Authorization':"Bearer $token"});
I agree with #Doug on this one - callable wraps this for you and will be easier -, but my use case required me to make HTTPS calls (onRequest in Functions). Also, I think you're just in the correct path - but you're possibly not checking it in your Cloud Functions.
In your app, you'll call:
_httpsCall() async {
// Fetch the currentUser, and then get its id token
final user = await FirebaseAuth.instance.currentUser();
final idToken = await user.getIdToken();
final token = idToken.token;
// Create authorization header
final header = { "authorization": 'Bearer $token' };
get("http://YOUR_PROJECT_BASE_URL/httpsFunction", headers: header)
.then((response) {
final status = response.statusCode;
print('STATUS CODE: $status');
})
.catchError((e) {
print(e);
});
}
In your function, you'll check for the token:
export const httpsFunction = functions.https.onRequest((request, response) => {
const authorization = request.header("authorization")
if (authorization) {
const idToken = authorization.split('Bearer ')[1]
if (!idToken) {
response.status(400).send({ response: "Unauthenticated request!" })
return
}
return admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
// You can check for your custom claims here as well
response.status(200).send({ response: "Authenticated request!" })
})
.catch(err => {
response.status(400).send({ response: "Unauthenticated request!" })
})
}
response.status(400).send({ response: "Unauthenticated request!" })
})
Keep in mind:
If I'm not mistaken, those tokens are valid for 1 hour, if you are going to store them somewhere, just be aware of this. I've tested locally and it takes around 200~500ms - every time - to get only the id token, which in most cases are not that big of overhead - but is significant.
It's going to be easiest for you to use a callable function, since that lets you:
Automatically send the current user's uid in the request.
Know very easily on the function side if a UID was provided in the request, and refuse service if none was provided.
The flutter plugin is here.
You should be able to do the equivalent work yourself, though, since callable functions are just a wrapper around normal HTTP connections. It's possible for you to get the ID token of the logged in user.
import 'package:firebase_messaging/firebase_messaging.dart';
.
.
.
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
#override
Future<void> initState() {
super.initState();
_firebaseMessaging.getToken().then((token) {
assert(token != null);
print("teken is: " + token);
});
}
Get your token from firebaseAuth and put in a string.
Future<Details> getDetails() async {
String bearer = await FirebaseAuth.instance.currentUser!.getIdToken();
print("Bearer: " + bearer.toString());
String token = "Bearer ${bearer}";
var apiUrl = Uri.parse('Your url here');
final response = await http.get(apiUrl, headers: {
'Authorization' : '${token}'
});
final responseJson = jsonDecode(response.body);
return Details.fromJson(responseJson);
}