oAuth2.0 - Fitbit does not return auth code (attributes cannot be empty error) - spring-boot

Ive been struggling with implementing the Authorization Code Grant flow for the Fitbit API. Ive set up the WebSecurityConfigurerAdapter, and I get correctly redirected to the Fitbit /oauth2/authorize page, where I can give permission. However, when I allow my application access, it says the following: authorization_request_not_found. Also, the url does not include a code.
I cannot really find good documentation on how to implement the next step using Spring Boot.
It would be greatly appreciated if anyone could point me in the right direction. Thanks
Stack:

The problem is in access token request. Following authorization code grant flow you need to set authorization header to basic. Your client_id and secret concatenated with a colon and encoded to Base64 will be your basic authorization header value.
You can find more info in official docs: Access Token Request
Implementing this in spring security is quite simple. Just follow this tutorial:
Custom Token Request
Convert method of CustomRequestEntityConverter class should look like this one below:
#Override
public RequestEntity<?> convert(OAuth2AuthorizationCodeGrantRequest req) {
RequestEntity<?> entity = defaultConverter.convert(req);
MultiValueMap<String, String> headers = entity.getHeaders();
String authorization = Base64.getEncoder().encodeToString(BASIC_AUTHORIZATION.getBytes());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setBasicAuth(authorization);
httpHeaders.addAll(headers);
return new RequestEntity<>(entity.getBody(), httpHeaders, entity.getMethod(), entity.getUrl());
}

Related

How to retrieve "state" param from the oauth response in spring boot

I am using spring boot, specifically spring-boot-starter-oauth2-client dependency for google login. Everything is working fine except that I need to send some details in the request and then retrieve them back from the response so that I can use those details. I did some research and found that I can do that by using state parameter while sending the Oauth Request. I can successfully set the "state" value in my custom OAuth2AuthorizationRequestResolver as below:
private OAuth2AuthorizationRequest customizeAuthorizationRequest(OAuth2AuthorizationRequest req,
HttpServletRequest request) {
String state = Base64.getEncoder().encodeToString("test".getBytes());
return OAuth2AuthorizationRequest.from(req).state(state).build();
}
This is all working fine! However, I'm not sure how to retrieve this value from the response. I can see there is OidcAuthorizationCodeAuthenticationProvider.java which is doing all the magic of creating the user after the authentication. I thought I could somehow override it and get the state value but I can't seem to figure out how to do it. I'm also thinking there maybe an easier way. What do you think?

How to get the access token sent in as header with Autentication Basic in Springboot

I have completed my most of the project but now I am stuck with a new problem. I have to extract the access token from the request which will be in header in Authentication Basic. This is confusing as first I used a simple GET method and was sending the access token in the request itself and extracting that with the use of #RequestParam. I have asked a similar question before but that was for the simple request from the request itself and now I have to do that from the header.
#GetMapping("/persons")
public String loadPersons(#RequestParam("access_token") String access_token) throws ParseException{
String decode_token = pd.testDecodeJWT(access_token);
String token = pd.jsondata(decode_token);
........................ More Code........................
I want to get that token from the request in Authentication Basic format.
I have tried some YouTube tutorials but as I have already done my project almost completely, I want to make minimum changes to it so that no further errors pop up.
Thanks in Advance
To get the value from the HTTP header , you can use #RequestHeader("headerValue") .
But what your question confuse me is that you are using Basic Authentication or JWT ? Basic Authentication is only about username and password and is nothing to do with the access token. It requires a HTTP header with the format :
Authorization: Basic <credentials>
where <credentials> is Base64Encode(username:password).
On the other hand , if you use access token formatted in JWT , the common practise is use Bearer in the "Authorization" header :
Authorization: Bearer <JWT>
So whatever you use , my advice is to use #RequestHeader("Authorization") to get value of the Authorization header first .Then decode the value according to your actual authentication mechanisms:
#GetMapping("/persons")
public String loadPersons(#RequestHeader("Authorization") String authHeader) throws ParseException{
//decode authHeader
}

How to use Restcall with Spring Security

In my Spring MVC application I am using spring security. It works fine so far, but I have to admit, I do not understand all the details.
In the same application the user can call some controller functions by rest api. When the user (lets say Tom) does this, his authentication is lost. Instead the controller is called by user anonymous.
I tracked down that "user switch" to the code below. Variable restCall contains an url to my application. That call would work for user Tom, if he would place it in the browser directly. Using the restcall, the user changes to anyonymous.
1) Can I prevent that, when the calling User (Tom) was already logged in?
2) As those services should be called by a user that is not already browsing the web interface of the application, I would have to find a way to login by the rest call itself.
private void callWebservice(HttpServletRequest req, String restCall) {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response
= restTemplate.getForEntity(restCall, String.class);
logger.debug(response.toString());
//assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
}
You need, for example, a JSON Web Token (JWT) Authentication.
Steps are the following:
1) Client does an authentication, a post request with username and password
2) If authentication is successful, server returns a token in which is coded the user
3) In your next call, GET or POST, you add JWT to your header, this way the server will know who you are, because server can decode the token, and can grant also the right authorities and functionalities

JAVA Spring Custom Authentication Using MongoDB for fetching stored user credentials

Hi Stackoverflow team,
I am facing an issue in my REST Call which I am clueless about after trying to dig into the HTTP errors.
Somehow the authorization isn't working , eventhough the generation and fetch of the JWT token is successful.
Short Description of what I have in my Springboot App :
(Available for analysis of the problem at)
https://github.com/vivdso/SpringAuthentication
A DbRepository call that talks to a backend MongoDb collection named UserAccounts which has roles and credential details stored including the passwords (Ciphertexts).
A JWT token generation mechanism that returns a token which has to be attached to the HTTP Headers for the subsequent API Calls.
The flow in short.
".....:8080/auth" method post Content-Type appliction/json body:{"username":"user","password":"sample"} Response should be a jwt token
and then
Try the autheticated url .....:8080/order.
****EXPECTED RESULT : Header" Authorization:{$jwtToken from step 6} Actual Result: :( Error : 403 forbidden, this should be fully authenticated and should let the user access this api. Expected Result: "Hello here is my order"****
This is just a simple application with not too many details to worry about.
Any help will be appreciated.
Thanks in advance.
in your code I couldn't find the filter registration.
Try to add it in the WebSecurityConfig.java
#Bean
public CustomAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
CustomAuthenticationTokenFilter authenticationTokenFilter = new CustomAuthenticationTokenFilter ();
authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationTokenFilter;
}
and then register it with
http
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
inside the configuration method
et me know
This was a role mismatch issue. Was not matching with the role in jwt.
Changed the code to correct the role and it worked fine -
public CustomDbRepository(){
List<String> roles = new ArrayList<>(1);
//roles.add("ROLE_USER");
roles.add("USER");

LinkedIn JS API token exchange to REST token using Spring Social for Linkedin

I'm trying to do the following:
Let the user authenticate and authorize through Linkedin using Linkedin JSAPI, then take the authentication details and send them to my server to get the user profile via server side communication.
I got the Linkedin button setup, got the authorization cookie all the way to my server (as described here), and was able to verify that the token is indeed signed correctly with my secret key.
Now I'm stuck at the point where I am supposed to take the token I got from JSAPI and exchange it for an access token.
This is the code I'm using, as mentioned it uses Spring Social for Linkedin, and it doesn't work as it throws a 401 Unauthorized response:
LinkedInConnectionFactory connectionFactory =
new LinkedInConnectionFactory(myLinkedinId, myLinkedinSecret);
OAuth1Operations oauthOperations = connectionFactory.getOAuthOperations();
AuthorizedRequestToken art = new AuthorizedRequestToken(new OAuthToken(codeIGotFromJSAPI, aSecretKey), whereDoIGetThisSignature);
OAuthToken accessGrant = oauthOperations.exchangeForAccessToken(art, null);
if (accessGrant == null) return null;
Connection<LinkedIn> connection = connectionFactory.createConnection(accessGrant);
if (connection != null) {
LinkedIn linkedin = connection.getApi();
return linkedin.profileOperations().getUserProfile();
}
What I'm actually confused about is the AuthorizedRequestToken object. The codeIGotFromJSAPI part is simple enough I think, it's just access_token, but what about aSecretKey, is it just my linkedin secret key? what about whereDoIGetThisSignature, how do I create that one? Do I use the same hash method as I used to validate the linkedin response and hash the access_token with my secret linkedin key? In the linkedin page, it says:
You need to pass four values as query parameters:
oauth_consumer_key, to identify yourself
xoauth_oauth2_access_token parameter, set to the value of the access_token field in the cookie.
signature_method set to HMAC-SHA1
signature, calculated as described in the OAuth 1.0a spec
So (1) is automatically done by the connection I suppose, (2) is the access token I provided, but how do I do (3) and (4)?
Lets suppose I get the following data in the JSAPI cookie set by Linkedin:
{
"signature_method":"HMAC-SHA1",
"signature_order": ["access_token", "member_id"],
"access_token":"AD2dpVe1tOclAsNYsCri4nOatfstw7ZnMzWP",
"signature":"73f948524c6d1c07b5c554f6fc62d824eac68fee",
"member_id":"vvUNSej47H"
"signature_version": 1
}
What do I need to do with it to go through the next step?
Use the following process:
Read the cookie
Transform "signature":"..." to &signature=...
Transform "signature_method":"HMAC-SHA1" to &signature_method=HMAC-SHA1
Transform "member_id":"..." to &oauth_customer_key=...
Transform "access_token":"..." to &xoauth_oauth2_access_token=...
Append all to the LinkedIn url plus ?
The LinkedIn JSAPI Token Exchange as described in Exchange JSAPI Tokens for REST API OAuth Tokens is currently not supported by Spring Social, according to a Spring forum discussion on this topic.
But there are implementation available to solve this task without Spring Social by using standard OAuth libraries available for Java. The LinkedIn user's access token, that you get from the exchange, can be put into a new AccessGrant object which can be used to create a Spring Social Connection<?> in the user's ConnectionRepository.
The code published in the LinkedIn developer forum discussion shows how to use Scribe to perform the exchange. The request that has to be sent to LinkedIn is a standard OAuth request but must ship the access_token field from the JSAPI token object as a HTTP query parameter xoauth_oauth2_access_token. The member_id that is also available to you is just for your information, and the signature allows you to verify both access_token and member_id without querying LinkedIn.

Resources