I am working on a project in which I need, not only to authenticate but also to have the real value of the token.
We have a Spring Boot application with oAuth2.0 Spring Security and the problem is that I am not able to find a method that gives me a valid token every time I call it.
At this moment, I have a post method raw coded in Java, but there must be a Spring Security implementation that does something like the following:
The first time that it is called, it asks for the token and stores it.
The following times checks if the token has expired and, just if it has expired, it asks for a new one.
Where could I find it?
EDIT
There are 2 different Spring Instances in my project: The Authorization server - which is a Cloud Foundry UAA server - and the resource server - which is the one that asks for the token and is coded by me.
The Authorization server uses AuthorizationServerTokenServices in JWT version and when the Resource server gets a token from there, I want it to be kept, not only decoded and used because I need to send it to another server.
Moreover, my application is not a web app, so there is no login page to log in on Facebook and I have to get the token using the Client Credentials Grant Type.
In my case, Single Sign-On is not possible because I have to use it not decoded.
This is my current implementation:
public String obtainAccessToken() throws ClientProtocolException, IOException {
HttpClient httpclient = HttpClients.createDefault();
String userPass64 = new String("User and password");
HttpPost httppost = new HttpPost("localhost:8080/uaa/oauth/token?grant_type=client_credentials");
httppost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httppost.setHeader("Authorization", "Basic " + userPass64);
//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
String responseBody = EntityUtils.toString(response.getEntity());
ObjectMapper mapper = new ObjectMapper();
TokenMessage tokenMessage = mapper.readValue(responseBody, TokenMessage.class);
return tokenMessage.getAccess_token();
}
From what I have seen is that there are few different ways that Spring security can handle this.
The default way is to have AuthorizationServerTokenServices interface handle it. And with it you can have different ways of storing the token. For example JDBCTokenStore, InMemoryTokenStore and JwtTokenStore. More about this here : http://projects.spring.io/spring-security-oauth/docs/oauth2.html#managing-tokens
But since I do not know what kind of application you are creating, you could maybe develop a single sign on functionality and let Facebook, for example, handle the authentication Token. Quite good tutorial about that with Spring boot can be found here: https://spring.io/guides/tutorials/spring-boot-oauth2/
Related
Trying to read data of specific envelopes from DocuSign using completely backend java process ... and after some trial and error I've obtained AccessToken with JWT grant but still getting authorization error when asking for actual data :(
Defined new integration key 9xxx7e
User Application: Authorization Code Grant
No secrets added
Service Integration - uploaded public RSA key
Added one Redirect URI (regardless I don't need any)
Manual confirmation of corresponding link : https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=9xxx7e&state=123&redirect_uri=https://my.redirect.net/DocuSign ... assuming it is just one-time action
Successfully requested Access Token using java code (using com.docusign:docusign-esign-java:3.10.1)
ApiClient = new ApiClient(ApiClient.DEMO_REST_BASEPATH);
OAuthToken token = apiClient.requestJWTApplicationToken(integrationKeyJwt, scopes, privateKeyFileContent, 3600);
Trying to get envelope data using simple HttpGet
HttpGet request = new HttpGet("https://demo.docusign.net/restapi/v2.1/accounts/6xxx1e/envelopes");
request.addHeader("Content-Type", "application/json");
request.addHeader("Authorization", "Bearer " + token.getAccessToken());
but still got 401 response with content:
{"errorCode":"AUTHORIZATION_INVALID_TOKEN","message":"The access token provided is expired, revoked or malformed. Authentication for System Application failed."}
Please any idea what is wrong? How to obtain correct Access Token?
P.S.: I also tried to get Authorization Code Grant without JWT or implicit grant but no luck without browser tough :(
I would recommend that you print the accessToken you're creating in a file and use in Postman. This will at least help you narrow it down to either the Token generation step or sending the request portion.
Let us know what you find.
Problem was/is with use of apiClient.requestJWTApplicationToken but apiClient.requestJWTUserToken is the way to go
I've been experimenting with Azure Active Directory access for Java using two sample projects:
1) https://github.com/AzureAD/azure-activedirectory-library-for-java which builds a stand-alone war using OAuth tokens for security, and
2) https://github.com/Microsoft/azure-spring-boot/tree/master/azure-spring-boot-samples/azure-active-directory-spring-boot-backend-sample for spring-boot embeded containers
I've come across quite a difference in the way the APIs can be used, that I can't understand.
In both cases, I get an OAuth token for AD by logging in with my Azure credentials.
In the Http response, I get an authorizationCode of the form:
AQABAAIAAAD.....
Then using the following URL as an authContext:
https://login.microsoftonline.com/{tenantId}
I get a AuthenticationResult by making the following call:
Future<AuthenticationResult> future = authContext.acquireTokenByAuthorizationCode(authorizationCode, redirectUri, credential, null);
in the Adal4j project (1), the AuthenticationResult's AccessToken is of the form:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6I...
Which I can use as a Bearer token in an HTTP call to retrieve the user's profile picture via https://graph.windows.net/myorganization/me/thumbnailPhoto?api-version=1.6
whereas in the SpringBoot AD example, the AccessToken returned from exactly the same call is of the form:
AQABAAAAAADXzZ3ifr-GRbDT....
and If I use that in exactly the same way to try to retrieve the user's profile pic, I get a 401 Unauthorized response
What's the reason for the difference in the form and use of these AccessTokens?
What's the reason for the difference in the form and use of these AccessTokens?
I assume that you got the access token is authorization_code not the bearer token.
As Rohit Saigal mentioned that you could use JWT.IO or JWT.MS to check that.
If we want to get the access token for Azure AD graph we could use the follow code to do that.
public String index(Model model, OAuth2AuthenticationToken authentication) {
...
DefaultOidcUser user = (DefaultOidcUser)authentication.getPrincipal();
String accessToken = user.getIdToken().getTokenValue();
...
}
Then we could use the access token to access the Azure AD graph api if you have assiged corrosponding permission.
I have a java/j2ee web application consuming SP web services but recently the SP site got migrated to 2013 and deployed in cloud/office 0365 due to which authentication got broken. SP people suggested to change authentication mechanism to SAML token based authentication and use Microsoft Azure AD. So i on boarded my application into Azure and received Client ID, Authority using which i am able to generate security token(used adal4j java api) . Now i need to complete below 2 steps to complete the authentication process in office 0365 to access SP 2013 web services.
Get access token cookies
Get request digest token
But not able to find any java based API for above 2 steps. Refereed below tutorial buts its something related to aps/.net
http://paulryan.com.au/2014/spo-remote-authentication-rest/
Please help me in providing sample code base for the same.
Appreciate your support
So you used Microsoft Azure Active Directory Authentication Library (ADAL) for Java?
In which case, have a look at AAD Java samples.
You want the ones that consume a Web API.
Per my experience, I think you can try to directly follow your refered article step by step to use the Apache HttpClient to construct the request.
For example, the code below is using the HttpClient to do the post request with the xml body to get the security token.
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://login.microsoftonline.com/extSTS.srf");
String xmlBody = "...";
InputStreamEntity reqEntity = new InputStreamEntity(
new ByteArrayInputStream(xmlBody.getBytes(), -1, ContentType.APPLICATION_OCTET_STREAM);
reqEntity.setChunked(true);
httpPost.addHeader("Accept", "application/json; odata=verbose")
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httppost);
String respXmlBody = EntityUtils.toString(response.getEntity());
//Parse the respXmlBody and extract the security token
You can try to follow the code above to get the response includes access token via do the post request with the security token body for the url https://yourdomain.sharepoint.com/_forms/default.aspx?wa=wsignin1.0, and use the code Header[] hs = response.getHeaders("Set-Cookie"); to get the Set-Cookie header array as access token.
Then using them to set the two headers Cookie for getting the request digest token, and parse the response body to extract the FormDigestValue as the request digest token.
web client: https://gcl-11.appspot.com/
source code: https://github.com/gertcuykens/gcl-11/blob/master/android/src/my/endpoints/EndpointsActivity.java
This example is using google endpoints with android. I managed to get it to work, except it is mandatory also for non authenticated requests to first login before I can reach the server without a bad username error. In the webclient it's not.
about:
EndpointsClient.Builder endpoints = new EndpointsClient.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential);
question:
Is it possible to use a anonymous android client for non user object api request in google endpoints? I tried to set a empty account name but then I get bad username?
credential = GoogleAccountCredential.usingAudience(this, AUDIENCE);
credential.setSelectedAccountName("");
If not, can I specify a default one without using getSelectedAccountName()?
Also why does this not return a user email like the webclient?
Message response = service.post("greetings/authed", null).setOauthToken(token).execute();
After discusion with Dan Holevoet above I tried a longshot and replaced the GoogleAccountCredential credential with HttpRequestInitializer noCredential and that suddenly worked for non authenticated request.
EDIT:
credential = null; also works.
I can successfully access Google Drive and Spreadsheet functionality from my application.
So I have an authorised instance of com.google.api.client.auth.oauth2.Credential.
Now I wish to execute a Google Apps Script that is deployed as a 'Web App'. This will also require authentication to run. This script runs in the browser if I hit the endpoint and am authenticated.
Here's some psuedo code :
String url = "https://script.google.com/a/macros/mycompany.com/s/xxxx/dev";
GenericUrl webAppEndPoint = new GenericUrl(url);
final HttpTransport httpTransport = AndroidHttp.newCompatibleTransport();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(currentCredential);
// Do POST for service
String requestBody = URLEncoder.encode("{\"name\":\"John Smith\",\"company\":\"Virginia Company\",\"pdf\":\""+getPdfBase64()+"\"}", "UTF-8");
HttpRequest postRequest =requestFactory.buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString(null, requestBody));
postRequest.getHeaders().setAccept("application/json");
postRequest.setFollowRedirects(true);
postRequest.setLoggingEnabled(true);
HttpResponse postResponse = postRequest.execute();
If I run the code I get the following error : com.google.api.client.http.HttpResponseException: HttpResponseException 405 Method Not Allowed
UPDATE : So - originally i was POSTing to the wrong URL ( i'd copied the redirected URL from a browser instead of the script URL )
The POST is now successful ( authentication included ) using the above code, but it still doesn't handle the GET redirect after submission. I can work with this now but it would be good to be able to get a response from the server.
I think that com.google.api.client.http.HttpRequest doesn't handle authenticated POST redirects properly.
Your pseudocode isn’t very illuminating; to really see what’s going on you’d need to show the actual HTTP traffic. I should say though that a 302 redirect to a specified redict_uri is a normal part of the OAuth 2 authentication flow.
1) you cant call an apps script with authentication. You need to publish it as anonymous access as a contentService.
2)you are also calling the wrong url. Call the service url not the redirected one that you get in the browser.