I am building an app that needs to consume an external api protected with a client_credentials OAuth grant, My configuration is very simple and I was struggling with it for a long time until it worked for a weird rason:
In my original code the configurations is like this:
spring:
security:
oauth2:
client:
registration:
AuthProvider:
authorization-grant-type: client_credentials
client-id: *****
client-secret: *****
scope: resource.READ,resource.WRITE
provider:
AuthProvider:
token-uri: ******
I get the following error:
org.springframework.security.oauth2.client.ClientAuthorizationException: [invalid_client] Client authentication failed (e.g. unknown client, no client authentication included, or unsupported authentication method). The authorization server MAY return an HTTP 401 (Unauthorized) status code to indicate which HTTP authentication schemes are supported.
but when I accidentally made a type in the authorization-grant-type field it worked, I wrote client_credentals instead of the correct client_crentials (without the i)
Question is why it works with a mispelled grant type?
when I accidentally made a type in the authorization-grant-type field
it worked, I wrote client_credentals instead of the correct
client_crentials (without the i)
No, you should carefully check and make sure that the changes you're making are saved properly & part of compilation. The following are valid grant type allowed as part of Ouath2 RFC.
password
authorization_code
client_credentials
implicit
refresh_token
For more details:
https://datatracker.ietf.org/doc/html/rfc6749#section-4.2.1
Related
I've set up a Spring Security application to use my AWS Cognito user pool as the identity provider.
Cognito authentication works as expected when I set my Cognito dashboard's callback url to http://localhost:9001/login/oauth2/code/cognito and set my spring boot's application.yml file's redirectUriTemplate property to the same value (the application.yml file is below).
When I access "http://localhost:9001", I am redirected to the AWS Cognito login and can authenticate and be redirected to my app just fine:
spring:
security:
oauth2:
client:
registration:
cognito:
clientId: "myClientId"
clientSecret: "myClientSecret"
scope: openid
redirectUriTemplate: "http://localhost:9001/login/oauth2/code/cognito" # Getting a "redirect_mismatch" error when using "https://mycorporatehostname.com/login/oauth2/code/cognito"
clientName: my-client-name
provider:
cognito:
issuerUri: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_zBBqRy5Wv"
userNameAttribute: cognito:username
When I deploy the same application, it becomes accessible through a DNS hostname (i.e: "https://my.corporatehostname.com"). so I updated my AWS Cognito dashboard's callback url, and my application.yml's redirectUriTemplate, to use this DNS hostname in the callback urls, meaning that the "callback url" on the Cognito dashboard, and the redirectUriTemplate in my application.yml file both become: "https://my.corporatehostname.com/login/oauth2/code/cognito"
Unfortunately, when I try to access "https://my.corporatehostname.com", I expect to be redirected to the AWS Cognito login screen, but instead get a redirect_mismatch error.
Is there a way to see what the redirect_mismatch error is? I believe I've configured my application correctly, and am not sure why it would work on localhost, but not when deployed.
Additionally, my DNS hostname is only accessible via my corporate intranet--it is not publicly accessible. I'm not sure if that makes a difference or not.
Any help would be greatly appreciated!
I using Google for authentication in my REST API, but it gives me only Session cookie for 30min and then all my requests are being failed.
How I can configure google button to keep me signed in?
I have searched a lot of pages trying to find any answers, but nothing is going to work.
My current status:
security:
oauth2:
client:
registration:
google:
client-id: {someId}
client-secret: {someSecret}
Then I used /oauth2/authorization/google endpoint to have JSESSIONID cookie and it gives me ability to handle requests for 30min.
And then I have to make it again and again. I want to keep my session for a long time.
As I understand while I searched this question, that rememberMe functionality in springSecurity do not support oauth2.
I have a simple microservices project with an api-gateway, a product service and keycloak as authentication server. I beleive that i made the configuration correctly because on the browser i get the right response, but on postman what i get back as response is the keycloak default login page (on HTML).
This is the response on the browser
This is the postman response
Postman cookies :
Api-gateway config :
spring:
cloud:
gateway:
default-filters:
- TokenRelay
routes:
- id: product-resource-server
uri: http://localhost:9191
predicates:
- Path=/product/**
security:
oauth2:
client:
provider:
my-keycloak-provider:
issuer-uri: http://localhost:2727/auth/realms/demo-microservice-realm
registration:
keycloak-spring-gateway-client:
provider: my-keycloak-provider
client-id: demo-cloud-gateway-client
client-secret: 39ea2ef6-90a7-47ca-9892-fda60127f47e
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
My service config :
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: http://localhost:2727/auth/realms/demo-microservice-realm/protocol/openid-connect/certs
server:
port: 9191
ProductController :
#RestController
public class Controller {
#GetMapping("/product")
// #RolesAllowed({"product_read"})
public String getProduct(Principal principal) {
return "Response from Product Service, User Id:" + principal.getName();
}
}
So what i really wanna know is if this is a postman Bug or it is a config problem (project, keycloak ...).
Actually i can't test any Post resquest for the same raison and because it not possible to test them on the browser.
I hope this is understandable.
Well, I added spring-boot-starter-oauth2-resource-server in the api gateway project and it works fine.
Please refer to this tutorial : Microservices – Authentication, and Authorization With Keycloak
In postman when you use Authorization type oAuth2. Postman redirect you to login page to get access token from keycloak and store it in memory via Get New Access Token button. Then when you send a new request to the resource endpoint via the Send blue button; Postman sets the available token on a header field (Authorization) and sends it to server. therefore when Authorization header not set in your request.(for example for the first time that you not get a new token yet) your gateway detects not authorize error and redirects you to login page.
but on browser, the authorization mechanism is different totally in the way you call endpoint. It uses stored cookie (JSESSION) not token. you can test it by delete all stored cookie in your browser.
I encountered the same problem.
When I sent the token request from Postman, I received a response with 200 code but body was in html, which is useless.
In my case I found out I just wrote wrong url. So the solution was correcting the called url.
Your url should look like this:
http://{wherever-your-keycloak-runs}/auth/realms/{name-of-your-realm}/protocol/openid-connect/token
But I had mistake in {wherever-your-keycloak-runs} part, so apparently I was calling the wrong part of the keyclock.
I have two authorized clients in my Spring MSAL application, like so:
azure:
activedirectory:
tenant-id: ${TENANT_ID}
client-id: ${CLIENT_ID}
client-secret: ${CLIENT_SECRET}
authorization-clients:
calendar-api:
scopes:
- ${CALENDAR_SCOPE}
azure-api:
scopes:
- ${AZURE_SCOPE}
If I leave either one of these clients in place, I can run my application, log in, and generate clients to call the downstream resource servers. But if I enable both clients, I get the following error:
[invalid_grant] AADSTS65001: The user or administrator has not consented to use the application with ID 'b31490c0-4ac4-4f8c-8f8e-d5addb72271d' named 'Frontend'. Send an interactive authorization request for this user and resource. Trace ID: 3f003263-5eb7-4f97-b29a-fe0337d80800 Correlation ID: 4ccb19ec-8ff9-442d-b1b6-a106aa6721eb Timestamp: 2021-09-25 09:58:41Z
How can I fix this?
I believe the answer here is to add the APIs under the API Permissions page, and grant them admin consent. Once I had added this admin consent, the error disappeared.
I am able to login with Facebook into my SpringBoot application only if I disable the "Require App Secret" option in the Facebook Developer application configuration.
When the extra (recommended) security check is enabled I get an error
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_user_info_response]
An error occurred while attempting to retrieve the UserInfo Resource: Error details: [UserInfo Uri:
https://graph.facebook.com/me?fields=id,name,email, Error Code: {message=API calls from the server
require an appsecret_proof argument, type=GraphMethodException, code=100, fbtrace_id=xxxx}]
It is evident that Spring Security tries to access Facebook (calling https://graph.facebook.com/me?fields=id,name,email) to retrieve the authenticated user but it fails to pass the extra parameter appsecret_proof.
It is not immediately clear (after digging into SpringSecurity documentation and forums) how I can let Spring add the extra token.
I had a very similar situation - I could not log in to my application using the facebook user account.
First make sure that the given client id and secret id are correct (sometimes it can be confused with your other project). If you are sure that the entered data is okay, I would start by checking the available permits. So open the facebook login plugin panel (you should have a tab on the right side of the screen).
For my case, the following configuration was sufficient:
What's more, check the available permission and features:
public_profile access is required to extract basic information of a user who wants to log in to your website. In addition, it is also worth adding an email request.
Also check the configuration for the facebook client, which allows you to get the user token:
spring:
security:
oauth2:
client:
registration:
facebook:
clientId: your-client-id
clientSecret: your-client-secret
redirectUri: "{baseUrl}/api/oauth2/callback/{registrationId}" # Note that facebook now mandates the use of https redirect URIs, so make sure your app supports https in production
scope:
- email
- public_profile
provider:
facebook:
authorizationUri: https://www.facebook.com/v3.0/dialog/oauth
tokenUri: https://graph.facebook.com/v3.0/oauth/access_token
userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email
In my case, the above configuration was enough for the user to authorize himself on an external website.