reactjs app with keycloack keeps redirecting - reactjs

Following https://scalac.io/blog/user-authentication-keycloak-1/ I have made the app and realm. Then it was showing cors error even though I have put http://localhost:3000/ as weborigin and put "enable-cors": true, in json. So I have put + as web origin. Now after login, it keeps redirecting between URLs or as logged in state and not logged in state.
How can I solve it so that it redirects to one URL only, or keep it as logged in state.
After login from keycloack UI in localhost:8080 it keeps jumping between these two states or URLs:
keycloack client settings:
Edit:
Actually this happens if init options has any value such as check-sso or login-required.

Related

Redirection error Laravel Passport PKCE - local

I have a React site trying to get access token from my Laravel oAuth portal (using Passport). As I understand from the documentation, I create the state,code challenge and code verifier on my react app. I create a url with the required parameters and make a redirection to /oauth/authorize. The complete code for the redirection is window.location.replace('http://portal.test/oauth/authorize?' + paramsStr). http://portal.test is my oAuth portal (using Valet) and paramsStr contains all my parameters: client_id, redirect_uri, response_type, scope, state, code_verifier, code_challenge, code_challenge_method.
I am redirected to the portal as I should which redirects me to the login form. Once logged in, I have to approve the authorization request. After that step, I am supposed to be redirected to my React app to verify the state parameter and then make a POST request to my oAuth portal to request an access token. (again, from the documentation)
The url in my browser is still http://portal.test/login (the oAuth portal url) where it should be http://auth.localhost:3006 (the React app). I do have kind of a popup that opens, showing the content of the React app but I have a problem with my cookies. In the first step, after creating the state,code challenge and code verifier, I store those (using react-cookie). If I check the cookies right after, I can see them. If I go to another page of my React app, I can see them. If I manually go to another url (like google for example) and then go back to my React app, I can see them. So I know that setting the cookies does work. But in that weird popup I can't access the cookies.
I guess that a redirection issue and I can't access them because the url in the browser in not the url of my React app. How can I fix that ?
Relevant code for the login
const [cookies,setCookie,removeCookie] = useCookies([]);
setCookie('code_challenge',code_challenge);
setCookie('code_verifier',code_verifier);
setCookie('state',state);
console.log(cookies); // this shows the 3 values
window.location.replace('http://portal.test/oauth/authorize?' + paramsStr;
Page I am redirected to within React app
const [cookies,setCookie,removeCookie] = useCookies(["foo"]);
console.log(cookies); // empty
In the url to /oauth/authorize the parameter redirect_uri is http://auth.localhost:3006. In the DB in the oauth_clients table, the redirect value is the same.

What is PostLogoutRedirectUris and signout-callback-oidc in signout flow

what is the purpose of
PostLogoutRedirectUris = { "https://yourclienthost:port/signout-callback-oidc" }
in Client Config please?
When I put it, IdentityServer logout page show confirmed logout message AND shows a link to redirect back to my application.
When I omit it, IdentityServer show confirmed logout message BUT NOT shows a link to redirect back to my application
Regardless of the options, IdentityServer still logs me out. So I am confused what that config does. Please help clarify. Thank you very much!
The purpose of PostLogoutRedirectUris in client config is security.
When the client initiates signout, the client opens a url like that:
https://[identity-server]/connect/endsession?post_logout_redirect_uri=https%3A%2F%2Fclient%2Fapp%2Fsignout-callback-oidc&id_token_hint=XXX&state=YYY&...
Pay attention that the client itself tells IdentityServer where to redirect to after signout. This means that the client might cheat IdentityServer to redirect to a malicious URI.
That's why a white-list of URIs is used on the IdentityServer side, which is called PostLogoutRedirectUris. The list contains all possible deployment locations of the client e.g.
"PostLogoutRedirectUris": [
"https://localhost:44321/signout-callback-oidc",
"https://client/app/signout-callback-oidc", ...
]
When the callback URI suggested by the client is not on the white-list, then
IdentityServer shows confirmed logout message but NOT a link to
redirect back to your application
The signout process continues like that:
.../connect/endsession above redirects to https://[identity-server]/Account/Logout?logoutId=ZZZ
The Logout action renders a page with the link back to the client ( https://client/app/signout-callback-oidc&id_token_hint=XXX&state=YYY&... )
On the same page there is also an iframe wich opens https://[identity-server]/connect/endsession/callback?endSessionId=TTT
This iframe renders another iframe which signs out the client by calling https://client/app/signout-oidc?sid=SSS&iss=https://identity-server
On the same page there is also some JavaScript which automatically opens the link from step 3 and goes back to your client app.
The /signout-callback-oidc route in a MVC client does nothing (probably; I don't know what it does) but it redirects to the home page. (*)
The signout from both IdentityServer and the client app is already complete in step 5. /signout-callback-oidc has nothing to do with the signout itself. It only provides a landing page back in the client app so that the user does not get stuck on a page in IdentityServer.
(*) More precisely, /signout-callback-oidc in the client app redirects to options.SignedOutRedirectUri which can be set during AddOpenIdConnect().
By defaut SignedOutRedirectUri == "/". I prefer to change that option to "/Account/Login". In this way I see the login page right after signout.
"/signout-callback-oidc" is just the default value of options.SignedOutCallbackPath. You can change that path but there is no benefit. This route is automatically registered and automatically handled by the middleware. You cannot write your own controller/action for that route.
PostLogoutRedirectUri is meant to redirect you when you log out of your client. It will, e.g. bring you back to your client application's home screen. When you implement a 'single' logout for your application, you stay logged in to IdentityServer.
Once you are logged out of IdentityServer itself however, no PostLogoutRedirectUri is used and the flow ends on the IdentityServer UI.
In this case, it probably means that you implemented your signout by calling SignOutAsync twice. Once for the local application and once for the IDP but I can't be sure without seeing your code.

Facebook Login with Cognito User Pools using Amplify's federatedSignIn

I'm trying to get Facebook login working with Cognito User Pools in a React project using aws-amplify.
I think I've set up the Facebook App and Cognito User Pool correctly by following various docs. Note that I'm using User Pools rather than Federated Identities.
I'm a bit stuck and confused on the React side of things. I've tried a few different guides, but all have the same outcome...
The Login button triggers this code:
Auth.configure({
oauth: {
domain: 'xxxxxxxxx.auth.eu-west-2.amazoncognito.com',
redirectSignIn: process.env.REACT_APP_FACEBOOK_REDIRECT_SIGN_IN,
redirectSignOut: process.env.REACT_APP_FACEBOOK_REDIRECT_SIGN_OUT,
responseType: 'token'
},
region: process.env.REACT_APP_AWS_REGION,
userPoolId: process.env.REACT_APP_USER_POOL_ID,
userPoolWebClientId: process.env.REACT_APP_USER_POOL_WEB_CLIENT_ID
})
Auth.federatedSignIn({provider: 'Facebook'})
After clicking the Login button, the page is redirected and ends up with this hash in the url:
https://localhost:3000/sign-in#access_token=xxx&state=xxx&token_type=Bearer&expires_in=3600
If I then call Auth.currentAuthenticatedUser(), I get no user ("The user is not authenticated"), and if I try Hub.listen("auth"), the only events that get fired are parsingCallbackUrl and configured - the page is then redirected and the signIn event is never fired.
If I then click on the Login button again (when the url has the hash with access_token etc), I will be successfully signed in. If I remove the hash, and try to sign in, it will fail as above.
Any ideas what's going on? Do I need to handle the access token from the hash myself? Why does Auth.federatedSignIn only seem to work if the access token is already in the hash?
I've just worked it out... the Auth.configure call needed to be moved out of the component and into App.js. Everything now seems to be working properly.

Flask: Unauthenticated user seeing cached app, not being redirected to login page

I have a flask app which serves an Angular JS app only to authenticated users.
Access control for the view which serves the app is implemented with #login_required from the Flask-Login package as follows:
# The app page is accessible only to authenticated users
#viewer_blueprint.route('/')
#login_required # Limits access to authenticated users
def serve_app():
return send_from_directory(
app.static_folder + '/app', "index.html")
However, I have noticed that after logging out, an unauthenticated user attempting to view this view does not get redirected to the login page, rather, they see a cached version of the app.
I have observed this behavior on Google Chrome and Firefox running the dev server.
How do I force no-caching only in the case of unauthenticated users? (I still might want caching for logged in users.)(Related questions / answers on stackoverflow seem to only address disabling caching period independent of authentication status, which strikes me as an unnecessary compromise.)
Examining the XHR log in Firebug seems to indicate the browser never even makes the original request to the protected app view. It just loads directly from cache.
EDIT 1:
One possibility would be to check authentication in the front-end app and force the redirect to the sign-in page if not authenticated, however I am interested in a back-end solution which can handle this 'automagically' so as to avoid the extra care needed on the front-end (after all, isn't this what #login_required, morally speaking, should / does claim to do?).

Django Rest Framework / AngularJS - Users do not get redirected anywhere after logging in, even though I have set LOGIN_REDIRECT_URL in settings.py

According to this link: http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/#adding-login-to-the-browsable-api
I need to add the following code to my URLs.py:
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
When I added this, users can log in by going to the "api-auth" URL and using the default DjangoRestFramework login interface. After a successful login, users are directed to "/test" because I have the following code in my settings.py:
LOGIN_REDIRECT_URL = '/test'
I wanted a way for users to be able to log-in using my own custom interface but by using DjangoRestFramework's built-in code for logging users in, so I created my own template. The login form in the template sends a post request to
api-auth/login/
and sends the user object (which consists of a username and password in JS) along with the POST request. No errors are returned, so I'm assuming the login is successful. However, it does not redirect to any URL (I was expecting it to redirect to "/test").
Any idea why it does not redirect anywhere, and how I can make it redirect to "/test"?
Edit: I am also using AngularJS on the frontend.
LOGIN_REDIRECT_URL is basically from django.contrib.auth so I wouldn't except other auth backends to use it, at least not necessarily/automatically
Also if you're logging through REST say from an AngularJS, even if after the REST API login is successful and returns a redirect response, there is no guarantee that the AngularJS app will navigate to that page because the login REST API was hit using an XHR request (from $http or $resource etc)
I'm using a slightly different REST auth lib than you, called django-rest-auth (not the BrowsableAPI that comes with DRF), I'm authenticating from AngularJS, and after the call is done with success, I simply navigate the app to a new URL
djangoAuth.login(username, password).then(function(){
// make angularJS navigate to new page when login is successful
// $location.path(...) or some other way
});
Bottom line is, since you have an auth API, you can make a small AngularJS page, with login form, then when login is successful redirect with AngularJS
Worth a look
I'm using these two libs that are meant to be used together, they offer REST auth over DRF, and optional a AngularJS lib to help with the frontend
https://github.com/Tivix/django-rest-auth
https://github.com/Tivix/angular-django-registration-auth

Resources