Oauth2 Login in Spring Cloud Gateway using KeyCloak - keycloak

I implemented oauth2 in Spring cloud gateway using KeyCLoak. Now I want all the request are permitted except those which have "/user" in the url. Following is my security configuration
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.cors()
.and()
.csrf()
.disable()
.authorizeExchange()
.pathMatchers("**/user/**").authenticated()
.anyExchange().permitAll()
.and()
.oauth2Login();
return http.build();
}
I am expecting when user enter the url "http://localhost:8066/user" it will redirect them to keycloak login page, but it is not working,it is not redirecting to the login page of Keycloak.

Read the doc for AnthPathMatcher and more generally what valid ant path are.
My guess is what you want actually is .pathMatchers("/user/**").authenticated()

Related

How to configure Keycloak for my Single Page Application with my own Login form?

I have a SPA (Vue) that communicates via REST with a Quarkus Backend. I would like to use Keycloak for Authentication/Authorization. However, I do not need the whole "Browser Flow" Keycloak feature, instead my SPA has its own Login Form to get a JWT from Keycloak (Direct Grant Flow). This token will be used to communicate with my REST Endpoints.
Frontend -> gets a JWT from Keycloak
Frontend -> gets access to protected resources with that JWT.
However I came accross this article that vehemently discourages devs from using the Direct Grant flow. So what now? Is there a way to still use my own login form with Keycloak?
Something along the lines of:
Frontend login -> Backend -> Keycloak Authentication/Authorization -> JTW
Frontend -> gets access to protected resources with that JWT.
I am slightly overwhelmed by all the different configuration possibilities in Keycloak and Quarkus. So far I managed to get a token from keycloak with a public client (direct grant), and that token is being used to access protected resources. My Quarkus backend knows the keycloak server too and communicates with it via a second client (acces type: confidential)
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/myrealm
quarkus.oidc.client-id=backend-service
#quarkus.oidc.credentials.secret=my-secret
However, I am not sure why this works at all since the secret is commented out. Why would I need it in the first place ?
One way could be to use the authorization code flow with a custom theme for keycloak : https://www.keycloak.org/docs/latest/server_development/
As you are using react, you can take a look at https://github.com/InseeFrLab/keycloakify which allows you to reuse your react component with keycloak theming.
(Disclaimer: I belong to the organization maintening this library)

Passing Bearer token from kong to keycloak to be authenticated and then procceds to api call

I have set up keycloak-oidc on kong, and I have a protected API behind kong. I am able to call keycloak through kong because I added a filter /auth/*. Below is my oidc configuration for keycloak.
I configured my REALM and CLIENT_ID on keycloak as follows:
When I call the protected API with Bearer token acquired from keycloak, I am unable to reach the protcted API as Keycloak returns
{ "error": "invalid_request", "error_description": "Missing parameter: username" }
I have turned off the Standard Flow, yet I am unable to get authenticated by keyclaok and be passed on to the protected API.
Please what am I doing wrong?
First of all, I had to upgrade my kong-oidc from kong-oidc 1.0.1 to kong-oidc 1.1.0, then I simply just updated my introspection endpoint in the oidc plugin configuration as shown below, in the images I shared in the question above, the introspection endpoint field was not present and hence could not be set until after the upgrade

How to authenticate curl (or Postman, or Ajax) call with Spring Cloud Gateway and Keycloak

I'm using Spring Cloud Gateway with Keycloak, and authentication works from browser.
But, there is no Authorization header with the token, but SESSION cookie instead.
I don't want to use cookies at all, but token instead.
Currently, if I post to http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token to get tokens and try to put access_token in Authorization header with Bearer it doesn't work, but returns login page.
Also if I add keycloak.js to browser page, and after successful login try to add xhttp.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
to Ajax call, it again returns login page.
So how to use Spring Cloud Gateway with Keycloak, from any client with provided valid token at all?
Here is my gateway configuration, and web app behind it with /web/ route doesn't have any security applied. Keycloak is configured with basic public client.
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http,
ReactiveClientRegistrationRepository clientRegistrationRepository) {
http.oauth2Login();
http.logout(logout -> logout
.logoutSuccessHandler(new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)));
http.authorizeExchange().pathMatchers("/web/private").authenticated()
.pathMatchers("/web/**").permitAll()
.anyExchange().authenticated();
http.headers().frameOptions().mode(Mode.SAMEORIGIN);
http.csrf().disable();
return http.build();
}
If you want to make requests to Spring Gateway with access token you need to make it a resource server: https://stackoverflow.com/a/66923312/11122338

Validate oAuth 2 access token in APIGEE without VerifyOAuthTokens policy

We are using Apigee as our Authorization Server (AS) and we have a few Spring Restful services deployed in IBM Bluemix public cloud which acts as our Resource server (RS).
Each of the services has an equivalent proxy service configured in Apigee. For the proxy services, we have configured the VerifyOAuthTokens policy to verify the token passed by the user and return an error if invalid token is passed
The problem is, since our RS is in the public cloud (no plans or need of moving to a dedicated or private cloud) the api endpoints are open and can be invoked by anyone who knows the url.Though the expectation is everyone should call the apis via APIGEE proxies but we cannot force that since we are in public cloud and there are no options of opening ports coming from apigee or something. We would like to take the following approach to secure the api endpoints.
Accept the Authorization header for each call
Take the token and call a validate token service in Apigee
For 2, We are not able to find an APIGEE api which can validate an access token similar to say googles
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=1/fFBGRNJru1FQd44AzqT3Zg
or Github's
GET /applications/:client_id/tokens/:access_token
Is there actually an external APIGEE service to validate a token?
If not, what would be the best way to make sure that only valid users with valid tokens can access the apis?
Thanks,
Tatha
Did you look at this post in the Apigee Community: Using third-party OAuth tokens
We did something similar to this but not using oauth tokens. We used Apigee to do a callout to a third party IDP (identity provider). The 3rd party IDP wasn't able to generate tokens but exposed a web service to authenticate the user. If the user was authenticated successfully (based on interpreting the result received back from the target endpoint webservice), then you tell Apigee that it was successful by setting the external authorization status to true (step #2 in the link).
NOTE: this has to be done inside an Assign Message Policy step PRIOR to the GenerateAccess token operation. Apigee interprets this as a successful authorization and then can generate a valid oauth token that the caller can then send along to access the protected API.

Accessing REST service after login within browser using oauth2 and spring security using java config

I have implemented Oauth2 using sparkl2 app. I am using spring-security as described in the sparkl2 app using java config. I can successfully get auth token using curl and i can invoke web service using curl.
My question is
How I can access my REST service within the same browser after login into my application? I am not sure what I am missing here?
Let me elaborate my question in more details. The way browser keep session after login and we can access any protected resource in the application, what is the best way to implement so that I can test my REST api from browser
spring security keeps it in session. Session id is stored in browser cookie, so its passed with each request to your service. Then spring security should take it and check if specific session(with user logged in) is allowed to hit this particular url.
I would start with configuring secure paths in your java config:
http.authorizeRequests().antMatchers().hasAnyRole(...)
or some other method instead antMatchers.
you probably have to log in user into spring security on some oauth callback, something like:
Authentication auth = new UsernamePasswordAuthenticationToken(user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);