Facebook Javascript SDK - Chrome issue of access token - facebook-javascript-sdk

I am facing one serious issue on chrome for facebook access token. Following is the code from where i get user id and access token. This access token is later used for accessing various facebook functions.
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
uid = response.authResponse.userID;
accessToken = response.authResponse.accessToken;
} else if (response.status === 'not_authorized') {
In chrome, when i load the page first time.. It comes fine with access token. but when i refresh it few times, sometime it gives me access token as 0. Due to this nothing works. CAn anyone please help me out of this?
David

You may want to try setting the forcing a roundtrip to Facebook's server on page load so that you can always get the most up to date status of the user. The JavaScript SDK automatically caches the login status the first time the user views the page, but you can override it like this:
FB.getLoginStatus(function(response) {
// this will be called when the roundtrip to Facebook has completed
}, true);
Just make sure that the forced roundtrip doesn't add too much unnecessary latency! You can read more on the page for FB.getLoginStatus(). The section about the forced roundtrip is about halfway down the page.
Happy coding!

Related

When to update JWT access token with refresh token

I made a Quasar App with an external authentification server. After the login I receive the access and refresh token. The refresh token is not expiring until I press logout. The access token expires after 10 minutes. So since I need the access token to get the data, this is possible for the next 10 minutes after login. Afterwards I have to call an API including the refresh token to get a new access token.
My question is, how can I make sure to always have a valid access token without logging in again?
As a User I expect to login and have access to everything until I logout. And if my App was for example 15 minutes just laying around and then I want to receive data, that's not possible.
Somehow I want to call the refresh token api silently, but when and how?
Is it common to refresh the token at a certain time interval, or on changing a page or every time I want to receive data?
I didn't find an efficient solution yet.
In a boot file I added the refresh token method. So every time the App was started, the token will be refreshed. For iPhone users for example the app won't be closed completely so the init-method will not be triggered until I completely close the App manually.
I guess to refresh the token before every API call is too much. Or is it?
My question is, how can I make sure to always have a valid access
token without logging in again?
You may use Axios response interceptors in the Quasar Axios boot file to check if a response has failed due to expired access token (based on status code eg 401).
axios.interceptors.response.use(
(response) => {
return res;
},
async(error) => {
if (error.response) {
if (error.response.status === 401) {
// Use refresh token here to get new JWT token;
// return a request
return axios_instance(config);
}
}
return Promise.reject(error);
}
);
Hope this helps!

Nuxt fetchUser Auth function isn't reactive and requires a hard refresh

Using Nuxt 2.15.3, with a Rails backend.
I'm trying to create a Google OAuth workflow in my app, and I'm having some trouble with the steps after getting the access code. Once the user authenticates with Google and gets redirected back with the access code in the URL params, I send a request to my own backend to save the access/refresh tokens in the User model.
NOTE: this google Auth flow is separate from my normal app sign-in/sign-up flow. I'm only using some Google APIs, so this has nothing to do with making a user account via Google OAuth, I'm only requesting access to some APIs in the user's Google account, namely the My Business API.
Now, my backend has a boolean google_authenticated field on the User table which gets set to true if the access/refresh token exists, which automatically gets sent to Nuxt as $auth.user.google_authenticated. This feature works fine, but my problem is that the page where the users get redirected to has a v-if that checks for this google_authenticated flag.
The template looks like this, obviously simplified for the sake of the question
<template>
<div v-if="googleAuthenticated">...</div>
<div v-else><a href="googleapis.com">Authenticate</button></div>
</template>
export default {
data() {
return {
googleAuthenticated: this.$auth.user.googleAuthorized,
};
},
async mounted() {
const accessCode = this.$route.query.code;
await this.$axios
.post("/users/google_oauth", {
access_code: accessCode,
})
.then((response) => {
this.$auth.fetchUser();
});
}
}
So as you can see, what I'm trying to do is to refresh the $auth.user.googleAuthorized automatically on mount when the user gets to the page with the code in the URL params. The problem is that $auth.user doesn't seem to be reactive, and the user needs to either navigate to another page or refresh the current page to get these changes to show up and for the v-if to trigger and to show the other div.
I can see from the dev console that the fetchUser() method does indeed get called, and I can see from the Vuex store that the auth/SET function has been called and that the $auth.user.googleAuthorized flag is set to true as well.
According to the Nuxt Docs, the $auth module is reactive, but I'm failing to see it. What can I do here to make these changes stick properly?
So it turns out it's a race condition (sorta).
What's happening is that once I tell my own API to get the access tokens from Google, that request obviously takes some non-zero amount of time. As such, Vue is waiting to get the 200 from my own API indicating that I've fetched the access token and can continue with using Google APIs.
So basically, by the time Nuxt is calling fetchUser() again, it's actually getting the user without the googleAuthorized flag set to true, because that just happens a tiny bit too slowly. It's not really something noticeable when you're just looking at dev tools though, since everything seems to be happening instantaneously more or less, but the timings are extremely close, which is the reason why it would sometimes work, and other times it wouldn't without a refresh.

Refresh token in Spartacus after user does an action

I want to ask if someone knows a possibility to refresh token after user do any kind of activity. Right now token gets created after user logs in but it never get refresh, only if token is expired and user tries to do a request, this functionality can be found in AuthInterceptor but in our current project we automatically log out if expired_at is less than current Date.
Does someone can give me some guidance? I have tried creating another interceptor and call function handleExpiredAccessToken from class AuthHttpHeaderService but no good response, my token tries to refresh many times ending in a loop.
Also we tried refreshing the token 5 minutes before the expiration time and refresh headers for request like follow code:
const stream = this.authStorageService.getToken();
stream.subscribe((tokenData) => {
if(tokenData.expires_at && ( +tokenData.expires_at - 300000 < new Date().getTime())){
this.oAuthLibWrapperService.refreshToken();
}
if(tokenData.access_token){
request = request.clone({
setHeaders: {
Authorization: `${tokenData.token_type || 'Bearer'} ${tokenData.access_token}`,
},
});
}
});
Thanks in advance.
Maybe you can leverage this back-end configuration property: https://help.sap.com/viewer/d0224eca81e249cb821f2cdf45a82ace/2105/en-US/3d3ea6a4d5fa486aa324ce278fa2afc3.html?q=oauthauthorizationserver.tokenServices.reuseRefreshToken
According to the docs, every time the access token expires (and Spartacus automatically refreshes it), the server will generate a new refresh token. I'm assuming this means the validity of the new refresh token will be reset (easy to check).
You can try to setup a silent refresh like in this repo. If you then call the silentRefresh function of the OAuthService class, it will do a refresh of the token in a iframe.

Disable Multiple login at Keycloak

It is possible to disable multiple login at Keycloak?
Example:
I logged in on my browser at my PC and I do a login on my mobile phone... at this moment, keycloak invalidade the token of my other browser.
It is possible?
Update:
This feature has been implemented in keycloak version 17.
See: https://github.com/keycloak/keycloak/issues/10077
Old workaround:
Keycloak does not have this feature implemented yet. If you want you can create your own custom authenticator, for that you should have sound knowledge of keycloak codebase. I was facing the same issue and came up with a workaround.
Keycloak maintains active sessions of a user as shown below:
Every time a user logs in through different device, a session is added in the above list, we can use the above info to limit the user session to one.
I'm heavily making use of keycloak admin rest APIs to get the session-related data and to delete the session: link here
Make an API request to your server when a user logs in:
client.js
componentDidMount(){
let auth = await keycloak.init({onLoad: "check-sso"});
if(auth){
const {data} = await axios.get(`/check_session/${keycloak.subject}`);
this.setState({isSessionValid: data.isSessionValid})
}
}
render(){
return(
{this.state.isSessionValid ?
<YourComponent/> :
<div> You are already logged in!</div>
}
)
}
server.js
const baseUrl = 'http://localhost/auth';
const realm = 'myRealm'
// check session of user with same credentials from different devices
export const checkUserSession = async userId => {
// initialize access token
await initializeAccessToken(baseUrl); // check admin rest api docs of keycloak
// get all active sessions of user
const sessions = await getUserActiveSessions(baseUrl, realm, userId); // check admin rest api docs of keycloak
// check if any session exists
if (sessions && sessions.length > 1) {
// sort with start time in descending order
sessions.sort((a, b) => b.start - a.start);
const currentSession = sessions[0]; // current logged in user's session
const previousSession = sessions[1]; // previously active user's session
/* I'm preventing current user to log in, for your case you can delete
the old session of this user here */
await deleteUserSession(baseUrl, realm, currentSession.id); // check admin rest api docs of keycloak
return { isSessionValid: false, sessionData:previousSession };
}
// user logged in first time
return { isSessionValid: true };
};
Looks like a lot of Keycloak users are interested in this feature so I am posting an answer which I found on my conducted research, this feature implemented by unofficial developer and here is what he shared
You can get the authenticators from my cloned branch:
https://github.com/mfdewit/keycloak/tree/KEYCLOAK-849-configurable-session-limits/services/src/main/java/org/keycloak/authentication/authenticators/sessionlimits
I've created 2 authenticators:
`RealmSessionLimitsAuthenticator`: limits the total number of sessions for a realm.
`UserSessionLimitsAuthenticator`: limits the number of session per user account and per client.
For now I advise you to copy them (including the factories) to your own project and make sure they are referenced in META-INF/services.
Also, change the AuthenticationFlowError.SESSION_LIMIT_EXCEEDED error to some value that exists in your Keycloak version. SESSION_LIMIT_EXCEEDED is added by me and only exists on my feature branch.
The downside is that you cannot provide the user proper feedback in case his session is denied.
If you have any questions on how these should be used, let me know!
Regarding the status of this task: I still have to write the integration tests before I can submit the merge request. But I'm planning to finish this soon. If anyone want to help writing these tests, I'd be grateful.
Still keycloak official JIRA i didn't find if they incorporated this feature in any recent version of Keycloak
Source
https://github.com/mfdewit/keycloak/tree/KEYCLOAK-849-configurable-session-limits/services/src/main/java/org/keycloak/authentication/authenticators/sessionlimits
These feature has been implemented in keycloak 17 : https://github.com/keycloak/keycloak/issues/10077

transfer authenticated user between native and web javascript

I am using parse.com and phonegap, and want to be able to pass user credentials between the native and phonegap/uiwebview part of the app.
I have a valid PFUser in the native side, and want to pass/create the same valid user to the web portion of the app.
Can a user be created using existing credentials, maybe Parse.User.current()._sessionToken?
Given a sessionToken and a User's objectId, you have all the information you should need to re-login a User on the JavaScript side. However, there is no supported method to do it. You would have to do something terrible like:
var user = new Parse.User();
user.id = "the object id";
user._sessionToken = "the session token";
Parse.User._saveCurrentUser(user);
user.fetch({
success: function(user) {
// Now the user is logged in.
}
});
However, this is unsupported, may not work, probably will break in the future, and may burst into flames at any moment. So don't do it. ;-)