Keycloak-js perform action after user authentication - keycloak

I'm using Keycloak for my auth server in a reactJs site. I have all the normal workflows working using keycloak-js, KeycloakProvider and useKeycloak. I need to have some custom redirection rules however when a user logs in based on their role. i.e.
If they log in from the home screen, then
a) If it is a normal user they are redirected to /dashboard
b) If it is an admin user they are redirected to /admin
If they tried to reach some protected screen, they should be redirected back to the screen they requested
Right now it keycloak always directs them to the last screen they were on and I don't see a way to capture the "on intial login" event.
Any suggestions?

Maybe it's sufficient to check for the roles after the init/login or alternatively the keycloak.idTokenParsed.preferred_username and then redirect after a successfuly auth to your desired path (eg React Router or history.push("/dashboard") (with the useHistory hook))?

What I ended up doing is creating a /login route that my login points to. The only thing it does is force authentication the redirect to the proper page.
const RoleRedirector = (params) => {
const { keycloak,initialized } = useKeycloak();
const history = useHistory();
useEffect(()=>{
if(keycloak && initialized){
if(keycloak.authenticated){
const { tokenParsed } = keycloak;
const { realm_access } = tokenParsed;
const { roles } = realm_access || [];
if(roles.includes("admin")) {
//This is a separate React site living under the common domain
document.location = "/admin/index.html";
}else if(roles.includes("manager")) {
document.location = "/manager";
}else {
history.push("/dashboard");
}
}else{
keycloak.login();
}
}
},[keycloak,initialized])
return <div/>
}

Related

Keycloak return url

Keycloak version 16.1.1
keycloak.init({onLoad: 'login-required'}).then(async function (authenticated: any) {
if (!authenticated) {
display error...
} else {
use token to call rest and go to account page
}
This all works fine. After login, account page is displayed with url
http://localhost:4200/accnt
After couple of second, page flickers and url changes to
http://localhost:4200/accnt#state=5758b505-a101-48a3-a3a2-d899bf3e0da2&session_state=a5d6e548-9ebc-4666-bc41-e92f00e4f216&code=8c93d0cf-5dde-40f3-bf1f-e81d2449f1d5.a5d6e548-9ebc-4666-bc41-e91a00e4f216.c7b376cb-05a2-49fa-8164-b8c932598bbd
Why is it happening and how can I stop this flicker and url change ?
Try changing the initOptions from { onLoad: 'login-required' } to
{
onLoad: 'check-sso',
silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
}
And adding a silent-check-sso.html file next to your index.html with a content:
<html><body><script>parent.postMessage(location.href, location.origin)</script></body></html>
Hope it helps!

Blazor Wasm Authentication

I am trying to build a blazor wasm app and trying to authenticate with Jwt token. I am facing with an interesting problem. When I login, I can't access the pages which has [Authorize] attributes. But after refreshing the page, authentication works. Where may be the issue?
I have figured out the problem. While you are doing login operations you need to force load. If you don't force load AuthenticationStateProvider is not refreshed.
async Task Login()
{
var token = await AuthenticationUseCases.LoginAsync(userViewModel.UserName, userViewModel.Password);
if (string.IsNullOrWhiteSpace(token))
{
NotificationMessage message = new NotificationMessage { Severity = NotificationSeverity.Error, Summary = "Info Summary", Detail = "Info Detail", Duration = 4000 };
NotificationService.Notify(message);
}
else
NavigationManager.NavigateTo("/", true); //true means force load
}

Aurelia Push State App Reload on Login and Logout

When configuring Push State with Aurelia and Visual Studio, I am getting an odd behavior where after I select login my entire app reloads instead of the router just pushing to the homepage. This also happens when I logout, I get to the login screen and it refreshes the entire app. I am using Aurelia Auth. Any assistance would be much appreciated.
I think I had the exact same issue some time ago and this was one of the reasons I switched back to pushState = false (but my infos may be helpful for you).
Anyways, the following issue describes what I was facing: https://github.com/paulvanbladel/aurelia-auth/issues/55
The problem is, internally the plugin sets href:
Login - https://github.com/paulvanbladel/aurelia-auth/blob/master/src/authentication.js#L95-L99
if (this.config.loginRedirect && !redirect) {
window.location.href = this.getLoginRedirect();
} else if (redirect && isString(redirect)) {
window.location.href = window.encodeURI(redirect);
}
Logout - https://github.com/paulvanbladel/aurelia-auth/blob/master/src/authentication.js#L139-L143
if (this.config.logoutRedirect && !redirect) {
window.location.href = this.config.logoutRedirect;
} else if (isString(redirect)) {
window.location.href = redirect;
}
What you need to do is avoid both conditions, i.e. set loginRedirect and logoutRedirect to the empty string (''). Then, do the navigation on your own via Aurelias router as I did in my example from the GH issue:
return this.auth.login(userInfo)
.then(response => {
console.log('You signed in successfully.');
this.router.navigate('/contents');
})
Of course, do the same router navigation on your logout method.

How to ensure that a controllers action is only being called once in sails.js app ..?

I am trying to implement user authentication in my sails app.. But I am encountering a problem in different controllers that their action are being called twice.. I have checked from my browser and the request is only being sent once.. Here is an example..
// api/controllers/AuthController.js
...
logout: function (req, res) {
console.log("Loggin out");
req.logOut();
res.json({message: 'Logged out succesfully'});
},
...
Following is my config/routes.js file. (using get for many action just for sake of ease for testing api..)
module.exports.routes = {
// By default, your root route (aka home page) points to a view
// located at `views/home/index.ejs`
//
// (This would also work if you had a file at: `/views/home.ejs`)
'/': {
view: 'home/index'
},
// testing the api
'get /users/check' : 'UserController.test',
'get /login' : 'AuthController.process',
'get /logout' : 'AuthController.logout',
'get /signup': 'UserController.add',
'get /verify/username/:username?' : 'UserController.checkUsername',
'get /verify/email/:email?' : 'UserController.checkEmail',
// add friend
'get /:user?/addfriend': 'FriendController.addFriend',
// accept request
'get /:user?/friendrequest/:request?/accept': 'FriendController.acceptRequest',
};
I have applied the isAuthenticated policy on this action.. which is like
module.exports = function(req, res, next) {
if(req.isAuthenticated()) {
console.log("Valid User");
return next();
}
else {
console.log("User not logged in");
return res.json({error: "Please login"});
}
};
No whenever I call <myhost>/logout I get the following json back..
{
"error": "Please login"
}
and here is the output on the server..
Valid User
Loggin out
User not logged in
This means that my controller's action is being called twice.. and this is not the problem with only this controller. The UserController.add action has the same problem. I seem to be doing every thing fine but I don't know where this problem is coming from. Can any one suggest how can I debug it . Or what could be the root of the problem. As far as I have check..
Browser is not sending the request twice.
The Controller's action is being called twice and so are the middleware assosiated with it.
Oh i have the same Problem a few weeks ago.
Sails also call the middleware on static files (like your styles.css). Console.log the req-object than you see what your browser requested.
There a two Ways to handle this Problem:
1.) Try to set skipAssets: true in your route (see: http://beta.sailsjs.org/#/documentation/concepts/Routes/RouteTargetSyntax.html)
2.) In your policy add an if-condition to skip assets (like ".js", ".css" and so on).

I cannot access other's facebook page insights though i connected through login pop up

i have create Facebook app for my external website and i created an Access token for that app with the "offline" access Permission (access token) with that token, i placed the Login button in my site ,i'm trying to fetch the insights data's,of those who log in through my External website with Facebook while connect i'm passing the offline_access, Manage_page **read_insights** permission, though permission granted by the page Admins i'm difficult to fetch the insights datas.Please some one help me to figure this
aspx file
<fb:login-button scope="manage_pages,offline_access,read_insights" size="large" style="opacity:.01 !important; width:250px !important;line-height: 31px !important;margin-top:0 !important;" onlogin="getPages()"> Sign In With Facebook Account </fb:login-button></div>
scrpit file
window.getPages = function () {
loadingImage($('#divSettings'), true, ($('.divSettings').outerHeight() - 50) + 'px');
//test
FB.getLoginStatus(function (response) {
if (response.status.toString().indexOf("connected") > -1) {
//User is conected and granded perms Good to go!
// alert('1');
FB.api('/me/accounts', function (resp) {
//var txtpageid = document.getElementById('ctl00_contentPlaceHolderRight_txtFBPageID').value;
var txtpageid = $.trim($('#ctl00_contentPlaceHolderRight_txtFBPageID').val());
// alert(2);
$('#spnFBsignMo').removeClass('Dsh_pop_MessTxt Pop_Facebk_Txt_error').addClass('Dsh_pop_MessTxt Pop_Facebk_Txt');
// if (response.error && response.error.type == "OAuthException") { alert('OAuth2.0 Exception Access token Expired or AppID miss matched'+'<br>'+'please contact Admin'); }
if (txtpageid != '') {
FBactualID = '';
for (var i = 0, l = resp.data.length; i < l; i++) {
var page = resp.data[i];
if (page.id == txtpageid) {
FBactualID = txtpageid;
varFBResponseFlag = true;
//alert('inside the page id validation');
}
}
}
getCheckedValue(FBactualID);
// alert('3');
});
}
else {
//measures to take the users to login again
// alert('You must login to Facebook to Validate the Page ID');
$('#spnFBsignMo').removeClass('Dsh_pop_MessTxt Pop_Facebk_Txt').addClass('Dsh_pop_MessTxt Pop_Facebk_Txt_error'); //DSh_Input_cus DSh_Input_width
loadingImage($('#divSettings'), false, ($('.divSettings').outerHeight() - 50) + 'px');
alert(4);
}
}); // login sta
i'm just give a call to with my access token to fetch information
something like this
https://graph.facebook.com/246355928767490/insights/page_views&access_token=xxxxxx-xxx-xx&since=2011-12-25&untill=2012-01-04
The call to
https://graph.facebook.com/app_id/insights
Will only give you access to insights about your app, not "other's facebook page insights". If you are actually trying to get your own insights, check first that there is any data by going to the insights page and looking at your specific application here:
http://www.facebook.com/insights/
If you are trying to get the visiting, logged in user's Insight stats for pages they own, there are already a number of answers to this. You will need to troubleshoot whether your user is indeed logged in or not but the function you are using to retrieve insights should be right. Have a look at theses previous answers:
Facebook page insights via API
Facebook Insights for Page via the API