How to refresh access_token on server side(JAVA)? - spring-boot

I am using a spring boot as my backend application.
I have stored our client's access_token, refresh_token, and access_id in my postgresql database.
Here is my code trying to get the new access token if token expired.
public void refreshGoogleIdToken(GoogleAuthEntity googleAuthEntity) {
LOGGER.debug("GoogleAuthService.refreshGoogleIdToken()");
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(googleAuthClientId, googleAuthClientSecret)
.build();
credential.setAccessToken(googleAuthEntity.getAccessToken());
credential.setRefreshToken(googleAuthEntity.getRefreshToken());
try {
if (credential.refreshToken()) {
Long newExpireTime = credential.getExpirationTimeMilliseconds();
String newAccessToken = credential.getAccessToken();
String newRefreshToken = credential.getRefreshToken();
LOGGER.debug("NewAccessToken: " + newAccessToken);
LOGGER.debug("NewRefreshToken: " + newRefreshToken);
LOGGER.debug("NewExpireTime: " + newExpireTime);
}
} catch (IOException e) {
LOGGER.debug("GoogleAuthService.refreshGoogleIdToken() - IOException");
e.printStackTrace();
}
}
Google return 400 error, and the description is: 400 Bad Request
{
"error" : "invalid_grant",
"error_description" : "Bad Request"
}
What mistake that I have make?
Thanks

I have been using OAuth2 with spring framework and have only encountered this error "Invalid grant" in case if refresh token is invalid, expired, revoked or does not match the redirection uri used in the authorization request, or is issued to another client
For your situation I think you should delete the stored refresh token / rectify it and debug your code again. This may be due to wrong token info stored in your PostgreSQL database while testing.

Related

Error : Authorization has been denied for this request

I have created web api method to insert some data. It works fine anonymously. But when I decorate the method with [Authorize] , I recieve message like "Message": "Authorization has been denied for this request." jwt bearer token was entered with the request.I run the function using Postman. Should I add any class to validate the bearer token?
[Authorize]
[Route("customer")]
public String customer(APICustomer APICustomer1)
{
try
{
insert_Customer(APICustomer1.custid, APICustomer1.custname, APICustomer1.status);
}
catch (Exception ex)
{
}
return "1";
}
Authentication is the process of validating user credentials and authorization is the process of checking privileges for a user to access specific modules in an application.
Please read the article for more detailed information: Authentication And Authorization In ASP.NET Core Web API With JSON Web Tokens

Outh2 Access Token Exception

I am implementing Outh2 for authentication in spring boot application.I am getting the authorization code successfully but when i am making post request to token url by rest template it is giving me exception 400 bad Request.By this exception i am not able to identify the issue.Below is my code.
ResponseEntity<String> response = null;
System.out.println("Authorization Ccode------" + code);
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> request = new HttpEntity<String>(headers);
String access_token_url = "https://www.googleapis.com/oauth2/v3/token";
access_token_url += "?code=" + code;
access_token_url += "&client_id =487786082511-ta7fnptb8dnd4lbq9lphbtbpll9eo1it.apps.googleusercontent.com";
access_token_url += "&client_secret =fS4KHLUUMOm-lYu8QtDOFcDV";
access_token_url += "&grant_type=authorization_code";
access_token_url += "&redirect_uri=http://localhost:8080/salesgoal/googleOuth2Success";
try {
response = restTemplate.exchange(access_token_url, HttpMethod.POST, request, String.class);
}
catch(Exception e){
e.printStackTrace();
Please let me know what i am doing wrong.
Thanks
Following google's oauth2 documentation
Exchange code for access token and ID token
The response includes a code parameter, a one-time authorization code that your server can exchange for an access token and ID token. Your server makes this exchange by sending an HTTPS POST request. The POST request is sent to the token endpoint, which you should retrieve from the Discovery document using the token_endpoint metadata value. The following discussion assumes the endpoint is https://oauth2.googleapis.com/token. The request must include the following parameters in the POST body:
Follwing their documentation there could be validations on the url parameters (which yield the 400 Bad Request error code)
Please check the following:
The redirect_uri is URL_encoded (by using UrlEncoder)
Url parameters don't contain spaces ( checkclient_id and client_secret )
Later Edit:
Also try following oauth2 specification by using 'Content-Type', 'application/x-www-form-urlencoded' headers on the /token request

Enable authenticator manually

Currently my client authenticates request only on case of 401 response:
this.client.authenticator(new okhttp3.Authenticator() {
public Request authenticate(Route route, Response response) throws IOException {
String credentials = authenticator.getCredentials();
if (credentials.equals(response.request().header("Authorization"))) {
throw new TraversonException(401, "Unauthorized", response.request().url().toString());
} else {
defaultHeader("Authorization", credentials);
Request.Builder newRequest = response.request().newBuilder()
.headers(Headers.of(defaultHeaders));
return newRequest.build();
}
});
But I'd like to change this behavior and be able to call it either manually or auto per first call? Is it possible somehow?
If the authentication is predictably required and not related to a proxy, then the solution is to implement an Interceptor instead of Authenticator.
OkHttpClient.Builder clientBuilder = ...;
clientBuilder.networkInterceptors().add(0, myInterceptor);
client = clientBuilder.build();
Example Interceptor https://github.com/yschimke/oksocial/blob/48e0ca53b85e608443eab614829cb0361c79aa47/src/main/java/com/baulsupp/oksocial/uber/UberAuthInterceptor.java
n.b. There is discussion around possible support for this usecase in https://github.com/square/okhttp/pull/2458. One issue with current Authenticator API is that it assumes a Response from the failed (401) request.

google ExchangeCodeForTokenAsync invalid_grant in webapi

i have implemented GoogleAuthorizationCodeFlow scenario from google api client dotnet and tutorial to get token from what my client sent to server as a code. but when i call flow.ExchangeCodeForTokenAsync , I get the following error :
{"Error:\"invalid_grant\", Description:\"\", Uri:\"\""}
I read google authorization invalid_grant and gusclass oauth 2 using google dotnet api client libraries but they didn't help me and. I think it must be very simple but I don't know why it doesn't work.
For client side , I have used Satellizer and this is my server Codes:
public bool PostExchangeAccessToken(GoogleClientAccessCode code)
{
string[] SCOPES = { "email" };
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets()
{
ClientSecret = "******",
ClientId = "********.apps.googleusercontent.com"
},
Scopes = SCOPES
});
try
{
TokenResponse token;
token = flow.ExchangeCodeForTokenAsync("*****#gmail.com", Newtonsoft.Json.JsonConvert.SerializeObject(code), "https://localhost:44301/",
CancellationToken.None).Result;
}
catch (Exception ex)
{
throw ex;
}
return true;
}
what is the problem?
On Github I found that I must use the Token from the client and use
GoogleAuthorizationCodeFlow.Initializer()
to create my UserCredential object.
You can check your google developer console settings.(Authorized redirect URIs)
Credentials => OAuth 2.0 client IDs => Your Application Settings => Authorized redirect URIs
You must add url. ("https://localhost:44301/")
My code :
flow.ExchangeCodeForTokenAsync("me", authCode, redirectUri, CancellationToken.None).Result;
Authorized redirect URIs
For use with requests from a web server. This is the path in your application that users are redirected to after they have authenticated with Google. The path will be appended with the authorization code for access. Must have a protocol. Cannot contain URL fragments or relative paths. Cannot be a public IP address.

403 Forbidden Request Using G+ API with good Access Token [duplicate]

I am developing a small web application wherein I am integrating with Google+ Domain API's.
I am using OAuth2 authentication.I have generated client_id and client_secret for my web application
from Google API console.
Using Google+ Domain API's, I am able to generate the access token.
Generating authorization URL
List<String> SCOPE = Arrays.asList(
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/plus.circles.read",
"https://www.googleapis.com/auth/plus.stream.write");
//Sets up Authorization COde flow
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(),
new JacksonFactory(),
"xxx","yyy",SCOPE).setApprovalPrompt("force").setAccessType("offline").build();
//Builds the uthorization URL
String url = flow.newAuthorizationUrl().setRedirectUri(<REDIRECT_URI>).build();
out.println("<div id='googleplus'></div><a href='"+url+"' rel='external' ><img src='googleplus.jpg'></a> <b>Configure</b></div>");
session.setAttribute("CodeFlow", flow);
After authorization
GoogleAuthorizationCodeFlow flow=(GoogleAuthorizationCodeFlow)session. getAttribute("CodeFlow");
//After authorization,fetches the value of code parameter
String authorizationCode=request.getParameter("code");
//Exchanges the authorization code to get the access token
GoogleTokenResponse tokenResponse=flow.newTokenRequest(authorizationCode).
setRedirectUri(<REDIRECT_URI>).execute();
GoogleCredential credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport()).setJsonFactory(new JacksonFactory())
.setClientSecrets("xxx", "yyy")
.addRefreshListener(new CredentialRefreshListener(){
public void onTokenErrorResponse(Credential credential, TokenErrorResponse errorResponse) throws java.io.IOException{
System.out.println("Credential was not refreshed successfully. "
+ "Redirect to error page or login screen.");
}
#Override
public void onTokenResponse(Credential credential, TokenResponse tokenResponse)
throws IOException {
System.out.println("Credential was refreshed successfully.");
System.out.println("Refresh Token :"+tokenResponse.getRefreshToken());
}
}).build();
//Set authorized credentials.
credential.setFromTokenResponse(tokenResponse);
credential.refreshToken();
Fetching circle information:
PlusDomains plusDomains = new PlusDomains.Builder(
new NetHttpTransport(), new JacksonFactory(), credential)
.setApplicationName("DomainWebApp")
.setRootUrl("https://www.googleapis.com/")
.build();
PlusDomains.Circles.List listCircles=plusDomains.circles().list("me");
listCircles.setMaxResults(5L);
System.out.println("Circle URL:"+listCircles.buildHttpRequestUrl());
CircleFeed circleFeed=listCircles.execute();
System.out.println("Circle feed:"+circleFeed);
List<Circle> circles =circleFeed.getItems();
while (circles != null) {
for (Circle circle : circles) {
out.println("Circle name : "+circle.getDisplayName()+" Circle id : "+circle.getId());
}
// When the next page token is null, there are no additional pages of
// results. If this is the case, break.
if (circleFeed.getNextPageToken() != null) {
// Prepare the next page of results
listCircles.setPageToken(circleFeed.getNextPageToken());
// Execute and process the next page request
circleFeed = listCircles.execute();
circles = circleFeed.getItems();
} else {
circles = null;
}
}
I get the below error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Forbidden",
"reason" : "forbidden"
} ],
"message" : "Forbidden"
}
com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
Note: I have also enabled Google+ Domain API in my Google API Console.
REDIRECT_URI ="http://localhost:8080/DomainWebApp/oauth2callback" since it's a web app.
Any Suggestions?
The first thing to check is that the application is making the call on behalf of a Google Apps user. If the user account is, for example, an #gmail account, the request will not be allowed. The Google+ Domains API only works for Google Apps domain users, and only for requests within their domain.

Resources