We have an application which is using spring-security-oauth2:1.0. I was trying to change it to a newer version, spring-security-oauth2:2.0.7.RELEASE. If I don't specify the scope or If I specify I single scope, the application works fine. I have a problem while requesting multiple scopes like read,write, which used to work in previous version.
The client I am requesting has all read,write and trust permissions.
When I was using spring-security-oauth2:1.0, to get a token I used to do a get call like
http://localhost:8080/oauth/token?grant_type=password&client_id=ws&client_secret=secret&scope=read,write&username=user#abc.com&password=temp123
If you see the scope parameter scope=read,write, by requesting this way I used to get a token with scope read and write.
If I try to do the same thing with Oauth2 version 2.0.7.RELEASE(with a POST request though), I get Invalid Scope exception because the tokenRequestis taking read,write as a single scope. The client I am requesting has read,write and trust permissions but read,write is not one of them.
If I try it with scope=write or scope=read, It works fine because read or write are part of the client's scope.
If I want to request for multiple scopes in OAuth2 2.0.7.RELEASE, how do I do that?
I found the correct way to do this. Instead of a comma separated scopes, you have to use + to separate scopes.
Ex: read+write , write+trust
So the following POST request worked fine.
http://localhost:8080/oauth/token?grant_type=password&client_id=ws&client_secret=secret&scope=read+write&username=user#abc.com&password=temp123
I hope it will help others :)
Related
I downloaded the Azure AD with spring boot from https://github.com/microsoft/azure-spring-boot. Its all nice and works well as long as I run theazure-active-directory-spring-boot-sample using
mvn spring-boot:run
as shown in the README file.
I am trying just a basic real-life scenario where the angular/react app is running separately on a separate port using npm. The moment I separated them out the main Filter AADAuthenticationFilter is only invoked once on the first request where it does token verification and never again for subsequent requests.
I went around and configured an nginx proxy so that the domains of these two are now same
localhost:9999 and I redirect based on the next path like web for the npm and app for the Spring boot. This enabled the cookies to be available at every request.
This helps because what I learned is that Spring uses cookies to maintain a session. But ideally, the AAD filter should revalidate the token every request.
But if I add a property of azure.activedirectory.session-stateless=true to my application.properties, as mentioned in the filter's code to make it stateless and validate on every request. It expects roles as a different attribute in AD instead of it being a group of the user.
I also don't understand get the behaviour, when the js files are embedded within the spring app and run all this works perfectly fine and the filter is invoked at every request. But when I separate them out it just doesn't work.
Any help or pointers would be appreciated.
I realize that a lot more info may be required for someone to debug the above problem. But I was just able to solve this - at least found the problem that was causing it. Like I mentioned earlier the problem started when I separated the client and spring APIs. And since the client was not able to send back the cookies set by server, due to change in domains I had to put a proxy server.
What I found out later was that every GET request was always invoking the AAD filter. Even multiple requests. But other requests like POST, PUT were failing. I tried disabling the csrf config in spring WebSecurityConfig.java -->> http.csrf().disable();
This solved my problem and now I receive a request and all works as expected. Now I am trying to figure out how not to disable csrf completely.
Thanks
Objective: I am trying to add authorization details to the JWT using a custom mapper for Keycloak, so that when a user logs in using the login page, his token will also contain all the permissions that are applicable.
As an example, here's the following code (decoded from the JWT):
"authorization": {
"permissions": [
{
"scopes": [
"edit",
"buy"
],
"rsid": "af23b104-1d7e-41ab-7600-6d5bb405ad8e",
"rsname": "Custom Resource"
}
]}
To be more specific, I'm trying to obtain a similar result as if using grant_type=urn:ietf:params:oauth:grant-type:uma-ticket, but directly from the default Keycloak login page.
What I tried: I tried making a custom mapper based on this example: https://github.com/mschwartau/keycloak-custom-protocol-mapper-example
I looked in the base code of Keycloak, but there doesn't seem to be any way to include authorization data in the tokens using the default behaviour. From what I could find, the data might be in the KeycloakPrincipal, but I am not sure if this is true, because there doesn't seem to be a way to obtain that. I might be mistaken, though, since I'm not very experienced with Keycloak.
As a side note, using the grant_type=urn:ietf:params:oauth:grant-type:uma-ticket in a rest call works, but it is not an acceptable solution, unfortunately.
TLDR; This can't be done, Keycloak doesn't let's you and/or doesn't have a mechanism implemented for this.
This can't be done as the token containing the permissions ie RPT token, is actually provisioned by Keycloak with invoking the authorization endpoints, and that in turn requires a user access token in the first place.
This is how it's currently done and implemented - so what you can actually do is, implement on your client app a mechanism for fetching that RPT upon login. You'll have to make two requests to Keycloak, one obtaining the JWT and the other one obtaining the RPT.
But all in all, this isn't encouraged, as the general idea is not to return all permissions when a user logs in, but to actually require allowed scoped and permissions for specific resources - for a specific user.
All this is documented on Keycloak Authorization
It's a bit vague I agree, so hopefully, you'll perhaps find some more useful info here
Obtain RPT without having to invoke Keycloak API twice
Please note again
you aren't supposed to require permissions for all available resources, for a user, but to request one by one and possibly extend your RPT. E.g. You would send a request per each required resource.
If for any technical reason, you cannot do it like this and you still want to require all permissions at once - the best yo can achieve, as already said, is getting the RPT token once a user logs in (obtains a JWT token). But this is still (minimum) two requests to Keycloak
In theory you could extend Keycloak in such a way, it returns permissions in the JWT right away, but this wasn't done by anyone so far as it would require a lot of work and keycloak tweaking, and would still be in question whether it's possible to do so.
In my application, user management is done through Keycloak. While testing my application end-to-end through Cypress, I came across an issue. When I sign up a user, it gives the following error:
We're sorry. An error has occurred, please login again through your application.
Cypress is adding something to a generated URL after I click the submit button, which is causing this issue. The same scenario tested through Protractor ran fine. I have noticed Cypress is appending session_code to the request URL. While doing manual testing, I don't get session_code.
Below is the URL generated through Cypress:
.../login-actions/registration?session_code=LsZbmsVVLwEH9s-xwFJ2JdDtaCu1_xzqAGOQCpjxGJI&execution=06fac3bb-fb19-474b-8659-2572586ae371&client_id=web_app&tab_id=PSlmfgdv0ls
Where as a manually generated URL is like following:
.../login-actions/registration?client_id=web_app&tab_id=PSlmfgdv0ls
My application backend is Spring Boot and the front-end is in React and Next.js.
It would be really helpful if anyone could guide us through this issue. Please let me know if you need more information about our application.
The Keycloak Authenticator documentation explains that the authenticate method checks the current HTTP request to determine if authentication requirements have been satisfied, and, if not, a challenge response is sent back. If the challenge response itself is authentication, then you'll see a URL with the session_code parameter.
It goes on to say that session_code, in the first URL example, pertains to the code generated from AuthenticationFlowContext.generateAccessCode(), which further explains:
String generateAccessCode()
Generates access code and updates clientsession timestamp. Access codes must be included in form action callbacks as a query parameter.
However, the "manually" generated URL, that does not include the session_code parameter, seems to indicate that the initial registration of the client has been successful and a client configuration endpoint is being used to make a GET request - a client read request - and all is well. Everything works fine.
Therefore, it seems that Cypress is being sent a challenge response (and potentially exposing a security flaw in your application). Possible reasons for this might be further explained within Cypress's documentation on Web Security.
Common Workarounds might provide you with a remedy, or, if all else fails, you might try Disabling Web Security for testing purposes as well.
I'm learning Web services. I have created an Rest API on local machine in eclipse. And the url looks like this http://localhost.com/Web/Test/Client
What It does is when I call this url as POST method with username and parameters in url's body, I get one token which I'm using somewhere else. Upto here its working fine. I pass username and password and I get a token once my API's code verifies the credentials coming in url's body.
So after that I read about security of Rest API so that no body could access my credentials which are coming with url. It says it needs to be converted into HTTPS from HTTP.
But I could not understand more how and where this security needs to be configured in my code. Do I need to write any code to achieve this or any settings are required ? I'm totally blank here.
Can anyone please help me to understand this and tell me what needs to be done to get HTTPS for my url ?
What you need to do here is create a self signed certificate and configure channel security. I highly recommend you to use spring security framework to get this thing done. This article will help you.
To require HTTPS for the login page modify your security configuration by adding the following:
http.requiresChannel()
.antMatchers("/login*").requiresSecure();
I got a Jersey Grizzly REST server running. Now i am receiving receiveing an URL from Microsoft with an Access Token however this access token is placed as an parameter after a # Symbol.
https://myURL.com/getToken/pathParam/#access_token=QWERwtrrgertWRDGTGHssef....
When i receive the Request from MS i cant read out the access token by any means, since it is filtered out. Is there a configuration where I can stop this and get the token as a param ?
From the looks of the fragment, it appears you are trying to accomplish an OAuth flow. The problem I see is that you are trying to implement a flow that is meant for the client side (or more correctly, user-agent side), and then trying to access the fragment on the server, which is meant to be interpreted on the user-agent side.
The #access_token.. tells me you are trying to implement the Implicit Grant. This is not recommended if you have access to the more common Authorization Code Grant. I don't know what Microsoft service you are using, but if they offer the Implicit Grant, then they should also offer the Authorization Code Grant, which is actually the most common in all of the Grant types.
If you want to stick with the Implicit Grant, then you will need to actually handle the redirect from the client (user-agent) side, meaning get your hands into writing some Javascript to postback the token to the server. You can see an example here.
I personally wouldn't recommend it. You can have a look at the Jersey OAuth 2.0 client. It will help with implementing the Authorization Code flow.