Spring Security OAuth2 supporting Facebook appsecret_proof - spring-boot

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.

Related

Keep user signed in for a long term using google in Spring Security

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.

Facebook Oauth2 authentication not working for spring boot application

I am building a spring-boot application which uses google/facebook oauth2 authentication. The application configurations set are as follows:
#Google
spring.security.oauth2.client.registration.google.clientId=<googleClientId>
spring.security.oauth2.client.registration.google.clientSecret=<googleClientSecret>
spring.security.oauth2.client.registration.google.redirectUri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.google.scope=email,profile
#Facebook
spring.security.oauth2.client.registration.facebook.clientId=<fbClientId>
spring.security.oauth2.client.registration.facebook.clientSecret=<fbClientSecret>
spring.security.oauth2.client.registration.facebook.redirectUri={baseUrl}/oauth2/callback/{registrationId}
spring.security.oauth2.client.registration.facebook.scope=email,public_profile
spring.security.oauth2.client.provider.facebook.authorizationUri=https://www.facebook.com/v13.0/dialog/oauth
spring.security.oauth2.client.provider.facebook.tokenUri=https://graph.facebook.com/v13.0/oauth/access_token
spring.security.oauth2.client.provider.facebook.userInfoUri=https://graph.facebook.com/v13.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)
For google, this is working well - the application has an authorization rest controller which redirects to the google auth end point. After logging in, I can see a code is returned and sent to a redirect URI {baseUrl}/ouath2/callback/google, which is exchanged for a token which is in turn parsed and used to construct a universal application-level Oauth2 bearer token (for use in my shared APIs etc).
For facebook, I am attempting a similar setup. The initial redirect works, and user is directed to a facebook login page with equivalent client_id / redirect uri parameters set:
https://www.facebook.com/v3.0/dialog/oauth
?response_type=code
&client_id=<fbClientId>
&scope=email+public_profile
&state=<state>
&redirect_uri=https%3A%2F%2F192.168.50.150.nip.io%3A8300%2Foauth2%2Fcallback%2Ffacebook
&ret=login
&fbapp_pres=0
&logger_id=e1036c5a-ac6e-448c-ab8g-655727eae993
&tp=unspecified
&cbt=1643459835928
&ext=1645463198
&hash=AeJog6HeUz9jlsDRQQo
However, when the code is obtained after login and sent to the redirect uri {baseUrl}/ouath2/callback/facebook, there is an error returned when my application attempts to access the FB User Info resource server:
I don't have any traffic capture from my backend to the FB User Info URI, so I can't see exactly what's being sent, but the response I get back is a server error:
[invalid_user_info_response] An error occurred while attempting to
retrieve the UserInfo Resource: Error details: [UserInfo Uri:
https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250),
Error Code: server_error]
Are there any known issues with the graph.facebook.com end points?

When using two authorized clients in Spring with MSAL, I get the error AADSTS65001

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.

How to test login based on Keycloak test using JMeter?

We have an app that has a keycloak login. I want to create a JMeter test that logs in using some credential than do some stuff. the problem is I don't know how to form the POST URL
https://something.something.something.something/auth/realms/test/login-actions/authenticate?session_code=D3XPlFteuLSReLVsPbmCYY8RwqJDPmxb9JI1dBtR1yk&execution=021d7cc9-048c-4f68-a295-6d145597dd8e&client_id=my-react-client&tab_id=ACD97a5Yb50”
How to get the other parameters for the Post URL inside the test. They are not in the previous HTTP response (accessing the login page) and there are not in the cookies. I know how to get only the client_id.
Keycloak supports 2 authentication protocols:
OpenID Connect
SAML 2.0
Looking into your URL it's utterly like that your Keycloak instance is using OpenID and looking into OpenID Configuration Options
client-id: <CLIENT_ID>
# the secret associated to the 'client' application
So my expectation is that this is something which doesn't change so feel free to keep it as my-react-client
Just in case get familiarized with OpenID Connect - How to Load Test with JMeter to learn more about the concept of bypassing login challenge in JMeter tests when it comes to external authentication providers.

Spring Session/OAuth2 multi tenant application / multiple cookies

I used Spring Session and OAuth2 to build a SSO for a multi tenant application and have an Application with different frontend clients and a backend server.
(I used this tutorial https://www.baeldung.com/sso-spring-security-oauth2).
So the problem now is that each client (Tenant) runs on a different domain than the backend server and so the backend server has only one cookie and a user can't login with on two different tenants at the same time. (Each tenant has different bearer tokens so only the cookie is the problem)
The Idea would have been to somehow configure spring to create a different SESSION cookie on the server too (Which I didn't manage to do/Don't know if this is even possible)
And additionally I don't understand why I need that cookie, since I am using a token based authentification.
I do understand that if I want to automatically log the user in if he closes the browser and opens it again, that I need to save some data on the client side (e.g. a cookie, but why use a JSESSIONID for that and don't save the bearer token in a cookie)
Additionally I do belive that after the login process the session cookie is used for authorization and not the oAuth token. (I removed it from the token store + refresh token and on the next request it simply created a new one)
So basically what I want to know is:
Can I somehow configure my backend to create one cookie per tenant ? (without running multiple instances of it)
Why do I need the session cookie ?
How is the user reauthentificated in oAuth after I delte the tokens from the token store, without having to enter the password again (I guess the session cookie is responsible for that tho)
My yaml config looks like this:
server:
port: 8082
servlet:
context-path: /ui
session:
cookie:
name: UISESSION
security:
basic:
enabled: false
oauth2:
client:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8081/auth/oauth/token
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8081/auth/user/me
client2:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8081/auth/oauth/token
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8081/auth/user/me
How OAuth2 works would be as follow:
The access token is granted for that tenant only and can't be used to access resource of other tenant.
The tenant website then need to store this access token to use later, either it can be stored in:
Cookie - you have no issue as each tenant have different domain.
Local Storage - you have no issue because it's also different storage.
SESSIONID is the cookie created by Spring and will not be used in this case.

Resources