SSO OAuth2Authentication session and server side http request - java

I am interested in opportunity to make server side http request to web server implementing same SSO authentication.
So assume I have: hello.org and hey.com that point to the same SSO server.
After I logged in hello.org I obtained:
OAuth2Authentication authenticationObject = (OAuth2Authentication) principal;
Now I would like to fire http request from hello.org server to hey.com
Request.Get("hey.com/get_data").execute().returnContent().asString();
But I hit authentication error code 401.
How can I retrieve all required tokens from OAuth object and make my request be authenticated?

the site hello.org is not supposed to call hey.com using the token provided to the client calling hello.org. That token is to be seen as a contract between the authenticated user and hello.org.
The hello.org server needs it's own client that is authorized to access hey.com.
So one common way to solve this is to create a "hello.org to hey.com" client with either key or certificate authentication against the sso provider, and then call hey.com with the token provided there, and then relay the info back to the user of hello.org.
Now that is if you want to call hey.com via hello.org and the user is unaware that hey.com was ever involved in the information provision.
If you on the other hand want to let the user access both hello.org and hey.com by signing in via hello.org you should check out either OpenId or SAML since bare bones Oauth isn't really designed for SSO or resource sharing.

Related

Keycloak JWT Validation using Java Spring Security + KC Adapter

I have gone through multiple blog posts and StackOverflow questions before writing my own. I have multiple queries and none of the posts answer them.
I am using Keycloak Spring Security Adapter to secure my legacy Spring application. I referred to the keycloak documentation here and was able to have OAuth flow running for me. I am using Client Id and Secret as Client Authenticator.
For eg: Access to localhost:8080/about.htm will redirect me to keycloak login screen and after successful authentication, I will be able to view my page. I am also using the below code to read the user details from the token,
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) auth.getPrincipal();
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
user.setUsername(idToken.getPreferredUsername());
Now when I test this application using postman and modify the generated access token, obviously the server gives an error. Ref : How to test application using postman.
However, this is the flow :
Client sends a request to the resource server, resource server checks for a token - if it exists, the client does the validation. If it doesn’t exist or is invalid, it redirects to the authorization server (KC).
My question is,
Who is validating this token? How does postman flow throw an error
if I fiddle with the token?
Do I really need to write a JwtTokenValidator in my application for
each request? Won't that be overkill?
If I use Client Authenticator as Signed Jwt with client secret, will this validation still be required? I am not using it as it introduces latency.
Please assist.
Answer to #1:
When you use any Keycloak adapters in your application (in your case the Spring adapter for Keycloak), that's the one who does the validation and redirects to the login if necessary. As part of the validation, it checks the signature of the token issued by Keycloak. So when you fiddle with the token, the signature doesn't match, hence it throws an error.
Answer to #2
No, you shouldn't need to implement a JwtTokenValidator. The adapter does it for you and a request should reach your endpoint/URL only if it has a valid token. You may only need to do that if you have a special requirements about validating the token (e.g. checking specific claim in the token against some service). Otherwise, you can safely use the claims in the token you received from the KeycloakSecurityContext. You can even setup authorization based on your URL patterns and Keycloak will enforce them too and allow the request to pass if user has necessary roles (like this example).
Answer to #3:
That option only changes the method used to authenticate your app to the Keycloak and has nothing to do with the user's token validation inside your app. In your current setup, when your app wants to communicate with Keycloak (e.g. to exchange auth code with auth token), it authenticate itself to Keycloak with a client-id/client-secret pair (otherwise Keycloak would not know it's your app and will reject the request).
If you choose the "Signed Jwt with Client Secret" option, your client can not just use a client-secret to authenticate to Keycloak. It should support the RFC7523 specification. So it's quite complex in compare with a simple clien-secret approach. In an environment in which you trust your clients (e.g. they're all known apps developed inside the company and you're not going to support public clients to join your Keycloak and use its services) it's quite common and safe to use client-secret approach.

What's the best way to authenticate / autorize a server using Oauth 2?

I have a server server1 that exposes an API which returns a list of purchased items. This API is protected by OAuth2. A user needs to be authenticated and have the role 'ROLE_SUPERVISOR' to access this API.
I want to be able to call this API from another server server2. This server calls the API of server1 without any user interaction (for backup purposes, amongst other things).
What would be the best way to authenticate server2 when calling the server1 API ?
I could create a specific technical user which has the role 'ROLE_SUPERVISOR', but I read that the client credential grant type might suit this case better (server to server authentication). I would then only have to create a new client application and register it in the authorization server. However, how do I add the role 'ROLE_SUPERVISOR' to a client application ?
Thanks.
I think that there are some terms being using the comments and in the question that are confusing the issue a bit.
So I need server2 to have the 'ROLE_SUPERVISOR' in order to access this API.
With OAuth 2.0, servers aren't the things with roles. A token has claims and those claims can be interpreted by an application. As mentioned in the question, you can obtain a token in a number of ways, one of them being the client credentials grant.
However, how do I add the role 'ROLE_SUPERVISOR' to a client application
It's also not entirely correct to say that clients have roles.
I believe the OP wants server2 to pass an OAuth 2.0 token to server1, and that the given token should have the appropriate claims in it such that server1 will grant the corresponding request with a ROLE_SUPERVISOR granted authority.
To get such a token with the client credentials grant, you'll need to configure a client in the authorization server:
#Override
protected void configure(ClientDetailsServiceConfigurer clients) {
clients.inMemory()
.withClient("id")
.authorizedGrantType("client_credentials")
.authorities("ROLE_SUPERVISOR")
.secret("{noop}secret")
}
Then, server2 can use the client id and secret configured to obtain a token. As already stated, Spring Security ships with filters for negotiating with authorization servers and adding the appropriate Authorization header to the call to server1.

Avoid SPNEGO authentication for each request

I have a webserver which is using Jetty underneath along with SPNEGO authenticator and login service. I am using Firefox to connect to this webserver and can see that authentication is happening properly. But the issue is for each request from web client authentication is happening again and again, rather than only at first request. Does Jetty store any information to differentiate between an authenticated and unauthenticated user ? If not then can someone please help to recommend how I can achieve that? Also what it means to logout a user already authenticated using SPNEGO ?
The problem is not SPNEGO authentication but how you are managing session.
Once authenticated create a HTTP session and add the user's details to the session, and using a Filter check that there is a valid session is present if not do the authentication else skip the authentication.

SSO authentication with SAML2 in Java and How to Execute JavaScript by Using HtmlUnit

In one of my developments (using kerberos authentication to loginalong with HtmlUnit) its working fine in all cases , facing an issue after hitting SSO authenticated links where the SAML2 used.
I have searched all the way there is no proper explanation to get more info on SAML2 authentication for SSO secured pages.
I`m completely new for SSO authentication and SAML2 authentication,is there any separate API for this? help me to know on more on this.
Could you please help or suggest what is the best process to pass the user/password to get the authentication.
Thanks
Authentication itself is not part of SAMLv2 specification. SAMLv2 defines the exchange of information about authenticated subjects. Authentication happens at the SAMLv2 IdP. How this happens in detail is up to the IdP.
It could be that the following is possible in your case ...
Use HTTP POST to send credentials to the Login URL of the IdP. Capture the session cookie returned by the IdP. Send HTTP request to the endpoint of the IdP which allows so called IdP-initiated SSO and specify 'HTTP Redirect Binding' and the Meta Alias of the SP (this is the SSO-enabled app from SAML point of view). The IdP would return a 302 , follow the redirect, the SP should consume the SAML assertion included as a query parameter and you should be able to access the SSO-enabled app.
You may read SAMLv2 tech overview (http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0-cd-02.html) to get some idea.

SAML2.0 SSO with the WSO2 Identity Server?

I need to use WSO2 Identity server with SAML for SSO for my internal application. I came across this beautiful
SAML2.0 SSO with the WSO2 Identity Server article
But i have two questions on this article which i am not sure how works
1) In 5th step it is said "Now the user is being redirected to IDP again. Now the IDP realize this user is already authenticated hence it would issue
a SAML Assertion without prompting any authentication challenge."
How will the IDP realize that user is already authenticated ?
As per my understanding it must be done based on session. Does it mean when authentication request goes from service provider 1 to Identity server (SP1 redirects the request to IS thru browser ), IS will first authenticate the credentials and if successful keep the user object under session.
Now when second authentication request goes to IS thru SP2, same session ID is sent (provided request is sent from another of same browser), IS fins already a user object associated with this session, so trust him. Is this understanding correct?
2)In step 2 it is said that " Now the SP1 can validate the SAML Assertion issued by IDP and let the user log-in. "
what is the specific field/value (under SAML response sent by IP) , SP1 will verify?
3) Where user credentials are stored. Is it on IS side or Service provider side?
Just explain how it works with WSO2IS 5.0.0
When user is authenticated to IDP by providing credentials. WSO2IS creates an authenticated session for user and cookie with is associated with the authenticated session set in to the user's browser. Cookie name would be commonAuthId. you can also find it in your browser once you are authenticated with WSO2IS using SSO. Then user is trying to access another SP using same browser, cookie would be sent in to the WSO2IS and it identifies that there is an authenticated session related to the cookie.
Usually, SP validates the SAML2 Response and Assertion. There are several validations that you can do. But most common would be
Signature of the SAML2 Response and SAML2 Assertion
Validity period SAML2 Response and SAML2 Assertion.
Audience restriction validation in SAML2 Assertion
Destination url and Recipient value
Normally Username would be extracted from the Subject identifier value. Also there may be attributes in the attribute statement, which SP can retrieve and do some validation over them as well.
End users are authenticated to the IDP. So credentials must be in IDP not with the SP. It is one of idea of SSO. Maintains the credentials in one place. WSO2IS is default shipped with LDAP based user store. Therefore end user credentials are stored in the LDAP server. However WSO2IS can be deployed with any existing user stores that you like

Categories

Resources