Execute an Authorization Code Grant Flow Using Java Spring Rest Api - java

I'm trying to call a 3rd party endpoint that requires authorization using Java spring rest Api, so I need to execute an Authorization Code Grant Flow.
I understand the flow where I need to first get the code then exchange the code for a JWT and finally use the JWT to be able to do the secure call.
What's not making sense to me is how am I suppose to set up a redirect URI when I'm using solely working with a backend rest api with no UI. Usually the user is redirected to a login page where they either login with a username/password or 3rd party accounts (google/facebook...)
After alot of googling, all the searches ended with guides to secure my own endpoints rather than access a secure endpoint from my spring boot service
Edit: It's worth mentioning that I'm using solely a backend with no front end (or MVC) whatsoever, after #Partha's comment I did the following:
First, I added a new login endpoint, when accessed via browser(this won't work with swagger/postman) it should redirect the user to the Authorization Server:
#GetMapping
public void login(HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Location", getAuthServerEndpoint());
httpServletResponse.setStatus(302);
}
Where I built the endpoint to have all the data needed (client_id,redirect_uri...) so it looks something like
https://idpserver.bla/oauth/authorize?client_id=xyz&redirect_uri=http://localhost:8080/token&response_type=code&scope=xyz
Now it sends me to the Login page of the auth Server, after I login, I expect it to redirect me to localhost/token (which is a get request that would retrieve the code and do a post request to get a jwt and save it) but instead, I'm receiving a invalid redirect uri and I'm really not sure if this is an issue from my implementation or the server's
EDIT2: I did a dumb mistake by NOT adding http://localhost:8080/token as a redirect url in the Auth Server since I assumed I didn't need to

Not really sure how are you trying.. idea here is .. your api server should have a get endpoint /login. In your controller of /login , you should redirect to IDP say http://idpserver.bla?client_id=xxx&grant_type=code&nonce=yyy&redirect_uri=http://localhost:8080/token ( note, its redirect, not make an api request ). So, with this, when you hit http://localhost:8080/login in ur browser, you should see it being redirected to IDP. now you enter ur credentials, IDP validates that and redirect back to http://localhost:8080/token?code=XYZABC or something similar. Your controller code of /token API should read the code from url param. and make a call (this is api call, not redirect) to IDP to exchange the code for a token ( idToken / accessToken) based on your scope. And using the token you should be able to access protected resources. Hope that helps

Depending if you are using MVC or Webflux a different approach will be required:
MVC: include a "security filter" to do that. You will be able to see an example in the following links:
MVC Securiry Manager
MVC Security Filter
MVC Security Configuration
Webflux: configure your own security manager. You will be able to see an example in the following links:
Webflux Securiry Manager
Webflux Securiry Context
Webflux Security Configuration
As you can see in both ones, an external service is called (using RestTemplate in MVC and WebClient in Webflux), to get the required authorization information and decide if the "logged user" pass the required security logic.
You can adapt it in the way you need.

Related

Create a custom identity provider and configure it with keycloak

I am working on a project where I need to create an application that shall act as an OIDC mediator between a client which only supports OIDC for authentication and a REST api. The REST api is able to generate tokens and give user info but does not support OIDC.
To achieve this I am thinking of using keycloak to handle the OIDC communication with the client and implement my own java application that keycloak can trigger to realize the authorization, token and userinfo endpoint (sort of a custom ownmade identity provider) handling the communication with the rest api.
I have created a realm in keycloak and configured the realm to use an Identity Provider Redirector with an Identity Provider I added in keycloak (user-defined OpenID Connect v1.0). In the identity provider configuration I have set all the URLs to point to my java application but the initial OIDC authorization call from the client just redirects to the redirect_uri with a #error=login_required without any of my endpoints in the java application beeing triggered.
I guess there is something I have missed.. I need to intervene the authorization flow so that I can pick up a query param from the authorization request that needs to be handled in my java application. I also need to map the token from the rest api into the token request (when this request comes from the backend of the client app), and finally map the userinfo object as a response to the userinfo request.
I really hope someone have time to point me in the right direction. Thank you so much in advance.
Edit:
I have added a sequence diagram to explain it better:
I need to intercept the authorization request call to pick up a custom query param (endUserString) that identifies the user. There will be no user login form. I need the param in my code that uses this towards the REST API. Both the token and the userinfo must be received from my APP and not from keycloak itself.
The Java Mediator may ask for a token in advance (A) and use this to access the Rest API (using a predefined clientId and clientsecret). Alternatively this token may be fetched for each method. To token must be used to retrieve customer info from the REST API (B). I want to wrap this with OIDC support without any login form. A browser will just redirect to the authorization flow with the endUserString identifying the end user. The customer info will be returned from the java mediator into keycloak responding this in the GetUserInfoRsp.
I think there might be a simpler solution than what you envisioned: implementing your own custom authenticator for Keycloak.
Keycloak has a notion of authentication flow which is a tree of authenticators than are provided by Keycloak or custom made. Each authenticator can be called to try to authenticate the user.
The most common one is the Username/Password Form which displays a login page to the user and authenticates the user if the provided credentials are valid. But you could imagine any type of authenticator such as an SMS authenticator or a magic link one.
You can find the existing Keycloak's authenticators on their repo and the documentation on how to create your own here.
In your case, you would need to implement your own logic where your authenticator would get the endUserString param from the request and call the REST API to validate the user's identity. You could fetch the REST API token at initialisation or for each request. You could also modify the user stored in Keycloak with data coming from the REST API's user info endpoint (common OIDC attributes or custom attributes).
Please note that the dev team announced Keycloak X, a sort of reboot of the project which will probably bring breaking changes to their APIs.
Also, please consider all the security impacts of your design as, from what you provided, it seems the authentication of a user will only rely on a simple query parameter which, if it doesn't change over time for example, feels like a big security hole.

Spring Security call login programmatically

I am developing an application and I am using Spring Security. My question is - is there a way to call the exact logic that is run when I send a post request to /login (default), but from within the programme?
Normally, I post my LoginUserDto object to /login endpoint to login. However, I am implementing facebook login now, so I am constructing my LoginUserDto on the server side from whatever data I get from facebook based on user's access token. Now I just need to call the same logic that I would normally call with the rest call to /login, but from within the code in order to return tokens.
Does anyone know how this can be done?
Thanks
You should look at Spring Security 5's inbuilt support for OAuth2, as this will be the easiest way to incorporate Facebook as an external Authorization Server. There is some good documentation which walks through what is necessary via OAuth2 Login. Additionally, I found working with the oauth2login sample code from the Spring Security Repository extremely helpful to understand how the application should be configured, and it has a section for integrating with Facebook.

How do you use pac4j for OAUTH2 in a multi-tenant environment?

I would like to use pac4j in a Java application to create a Tomcat filter or Tomcat valve. The filter or valve must support OpenID Connect using standard OAUTH2 authorization code flows. Even better would be to build on top of j2e-pac4j to do this, but I cannot use the OAUTH2 filter in j2e-pac4j. My filter or valve needs to modify the request object by adding an HTTP header. The web app behind the filter/valve requires the HTTP header, and it's third party so I can't change this.
I will use Open ID Connect so I can get the JWT, but other than using the JWT and its contents and perhaps the userinfo endpoint of Open ID Connect, I am simply doing a standard OAUTH2 flow. Here's the complication: The server I will redirect to for authorization supports multiple tenants. This means that the URL I redirect to will have the tenant name in the URL. This means that instead of a URL like
https://authorization.server.com/oauth/authorize
(Note, leaving off ?response_type=code&scope=openid&client_id=myclientname&state=nonce&redirect_uri=... for the sake of clarity.) I will be required to redirect to a URL like one of:
https://authorization.server.com/tenantname/oauth/authorize
https://authorization.server.com/oauth/tenantname/authorize
https://authorization.server.com/oauth/authorize?realm=tenantname
How do you do this with pac4j, or better yet, j2e-pac4j? I've been told that pac4j will not support this, where every client potentially uses a different redirect URL for authorization.

Spring Security OAuth2 cookies

I have OAuth2 implemented in my app with Spring Security. Currently, it works with the "access_token" request parameter. Where can I add some customization to also accept the token from a cookie?
You cannot get the token from a Cookie - using oAuth, the only way to get it is via a call to the oAuth server, getting a code, and then getting the token...
You can read the oAuth spec.
If you talk about the application-end (and not the oAuth), it might be possible.
Checking the token is the responsibility of the application that holds the protexcted resource. There, rather than getting the token from the header of the request, it can check a Cookie instead.

Can I use FORM and BASIC authentication together in my Java webapp?

Is there any way to use FORM and BASIC authentication together in my webapplication? I have a RESTful interface in it and I'd like to allow scripts to use it with the simple BASIC auth method but I'd like to have the FORM based auth for web clients as well. I'd like the webapp respond with 302 Moved Temporarily redirecting to the login page for unauthorized requests, but if it finds that the client is sending the BASIC authentication's HTTP headers with username and password, then accept them just like in BASIC authentication.
I see that this is not possible with a single web.xml configuration but wondered if anyone else has some solution for this.
Can you use a filter?
Inspect the request for your headers. If present do the login process and add session data etc. to the request. If it fails then either ignore it or redirect.
If I configured container auth then my code was never invoked without authentication. So the answer is no. Jenkinks CI and similar software use FORM based authentication for a restricted set of web resources and make use of Spring Security where things are more flexible.

Categories