Postman has Authentication helpers to help with authenticated calls and I'm trying to use the OAuth 2.0 helper to call a REST server created by JHipster using Spring (Security, Social, etc).
I've tried a lot of configurations, this is the screen (client ID and Secret were masked):
For the Authorization URL I've tried:
http://127.0.0.1:8080/oauth/authorize
http://127.0.0.1:8080/#/login (the app's login route)
The closer I get from receiving a token back to Postman is:
I don't know why it's erring like this. Maybe I'm setting the Callback URL incorrectly? Do I need to do this in the server or in the client (AngularJS)?
Does anyone have any idea of what's wrong? I appreciate your help.
JHipster is currently setup to use the "password" oauth2 grant type. The helper oauth2 helper only seems to work with "authorization code" and "client credentials" grant types.
What you'll want to do is first call your app's token endpoint directly as the angular app does in
src/main/webapp/scripts/components/auth/provider/auth.oauth2.service.js
POST http://localhost:8080/oauth/token?username=MY_USERNAME&password=MY_PASSWORD&grant_type=password&scope=read%20write
where your username and password can be "user" and "user" respectively, for example and with one header set:
Authorization: Basic AAAAAA
where AAAAAA is your (clientId + ":" + clientSecret)--all base64-encoded. You can use https://www.base64encode.org/. For example if your clientId is "jhipsterapp" and your clientSecret is "mySecretOAuthSecret", replace AAAAAA with "amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==" since that is "jhipsterapp:mySecretOAuthSecret" base64-encoded.
That should return you an access_token. Now hit your API endpoints by calling them with the access_token from your password request in your header like this.
Authorization: Bearer access_token_from_earlier_token_request
Update: if you're using microservices and UAA, then see Niel's answer https://stackoverflow.com/a/45549789/1098564
To build on #sdoxsee's answer:
Currently (August 2017) JHipster generates a class called UaaConfiguration with the configure(ClientDetailsServiceConfigurer) method setting up the client ID, client secret, scope and grant type. Refer to these settings (including the referenced JHipster properties in the application*.yml) to populate the Postman authentication helper, using /oauth/token as both Auth URL and Access Token URL.
Example:
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
/*
For a better client design, this should be done by a ClientDetailsService (similar to UserDetailsService).
*/
clients.inMemory()
.withClient("web_app")
.scopes("openid")
.autoApprove(true)
.authorizedGrantTypes("implicit", "refresh_token", "password", "authorization_code")
.and()
.withClient(jHipsterProperties.getSecurity().getClientAuthorization().getClientId())
.secret(jHipsterProperties.getSecurity().getClientAuthorization().getClientSecret())
.scopes("web-app")
.autoApprove(true)
.authorizedGrantTypes("client_credentials");
}
And,
jhipster:
security:
client-authorization:
client-id: internal
client-secret: internal
Means your authentication helper should be populated as follows:
Related
I am trying to implement a simple Spring OAuth2 resource server using google as OAuth server.
Basically, I've been following guides like this one spring-oauth2-with-google
application.yml:
spring:
security:
oauth2:
client:
registration:
google:
client-id: *******.apps.googleusercontent.com
client-secret:********_
scope:
- email
- profile
- openid
resourceserver:
jwt:
issuer-uri: https://accounts.google.com
jwk-set-uri: https://www.googleapis.com/oauth2/v3/certs
SecurityConfig.java:
#Configuration
public class SecurityConfig {
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.formLogin(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
.sessionManagement(sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
;
return http.build();
}
}
UserController.java
#RestController
#RequestMapping("/user")
#RequiredArgsConstructor
public class UserController {
#GetMapping("/{id}")
public void getUser(#PathVariable String id) {
System.out.println("Id: " + id);
}
}
I am able to get the google JWT through postman as described in the guide, but no matter how hard I try, when I try to consume my end point, through postman, the response is always 401. I have already tried to set a space between the Bearer keyword and token_id.
Error in postman:
Bearer error="invalid_token", error_description="Invalid token", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
but if i review the token in google token info the result seems ok:
"issued_to": "263667859573-jve8vplquh7qn4ft7aaj1t1m9boaq5d6.apps.googleusercontent.com",
"audience": "263667859573-jve8vplquh7qn4ft7aaj1t1m9boaq5d6.apps.googleusercontent.com",
"user_id": "112897290372529438679",
"scope": "openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
"expires_in": 3296,
"email": "javier#email.com",
"verified_email": true,
"access_type": "online"
Maybe, the access-token you get from Google is just not a JWT but an opaque token, in which case configuring your resource-server with a JWT decoder won't work. try to "open" one of your access-tokens in a tool like https://jwt.io to be sure.
I couldn't find a standard introspection endpoint for such Google opaque tokens, just https://www.googleapis.com/oauth2/v3/tokeninfo to which you can submit access_token as request param. If token is valid, you'll get claims in response. So, you could actually configure your resource-server with token introspection (instead of JWT decoder), providing your own token introspector to call the tokeninfo endpoint, check the response and either throw an exception or return an Authentication of your choice.
http.oauth2ResourceServer().opaqueToken().introspector(...);
But this is quite some work and introspection is far less efficient than decoding JWTs (first requires to submit token to Google for each and every incoming request on your resource server, when fetching public key only once for all request is enough for second).
It is likely that Google just doesn't want us to use their authorization-servers for our own resource-server except for a few limited cases (and I'm not sure which ones).
An alternative for you is using another authorization-server capable of federating "social" identities (Google, of course, but also Facebook, Github, etc.). Plenty do so: Keycloak is a famous on premise solution, but if you don't want to bother at maintaining an authorization-server yourself, you could have a look at SaaS like Auth0 (which has a free tier). Those two are just my current preferred in a galaxy of solutions, just search for "OIDC authorization-server" and choose your own.
I am recently working with Uipath Orchestrator API and I see that they use Bearer token to authenticate. But I am confused and I do not know if this way of authentication is oAuth or it can just be called Bearer Authentication.
So for API authentication, it depends on what orchestrator you are using.
On-Premise
If you are using an on-premise installation of Orchestrator you would send the following JSON body to your Yourorchestrator.com/api/Account/Authenticate
{
"tenancyName":"default",
"usernameOrEmailAddress":"your username",
"password":"your password"
}
you will get a JSON string returned and you want to extract the value for key result this is your authentication token.
Now that you are authenticated you can send your requests with the following header
Name - Authorization
Value - Bearer + your token from above
This is your authentication done.
Cloud
If you are using UiPath cloud instance of orchestrator you will need to send the following JSON body
{
"grant_type" : "refresh_token"
"client_id" : "ClientId"
"refresh_token" : "UserKey"
}
ClientId and UserKey are generated through the cloud instance of Orchestrator
You must also send the following header along with the JSON Body
Name - X-UIPATH-TenantName
Value - Your tenant logical name from orchestrator
Similar to the on-site orchestrator, this will return an authentication token, however, you will need to extract the value for key access_token.
To use this, you send the request with the following 2 headers
Name - Authorization
Value - Bearer + your token from above
Name - X-UIPATH-TenantName
Value - Your tenant logical name from orchestrator
There are some quite useful examples at https://postman.uipath.rocks/?version=latest
It can be quite fiddly to start with, and on-prem Orchestrator is definitely easier to connect with than Cloud orchestrator. I would definitely recommend using Postman to build your API calls
For my API testing, I have been getting the Authentication Token with the help of Postman. API uses OAuth2.0 for authentication.
While using Postman, I am entering the details like Token Name, Grant Type, Access Token Url, Client ID, Client Secret, Scope, Client Authentication. Once clicked on the Request Token, Bearer token is received and is updated in the Header of the request. Please refer the image attached.Getting OAuth2.0 bearer token with Postman
But now, I want to do it with Rest Assured using Java. Hence I want to know the code how do I get the Bearer token by using Rest Assured?
Assuming you are sending the client id secret and other details in the Query Parameters, for the GET and your response header access_token has the value you are looking.
public class Sample {
String oauth_token ;
#BeforeTest
public void sampletest() {
oauth_token = RestAssured.given().auth().basic("username", "password").
.queryParams("client_id", "client_id_value")
.queryParams("client_secret", "client_secret_value")
.queryParams("grant_type", "authorization_code")
.queryParams("redirect_uri", "https://someuritoredirect")
.queryParams("otherparams", "sampleparam")
.when().get("https://uri.to.get.hostname.com/oauth2/access_token")
.then()
.statusCode(200)
.extract().header("access_token");
}
}
I'm developping a Rest API, MyApi.
In there, I'm using Feign (and swagger codegen) to generate a client for another API, let's call it Ext-API.
The user will have called Ext-API previously and among other things will have retrieved a JWT Token.
He'll then call my API using Basic Auth and in the body it'll give me the JWT token.
I'm to use this JWT token as auth header to connect to Ext-API from my API and do some more stuff on behalf of the user.
However all example of Oauth & Feign example rely on the Oauth also being used to connect to the API using the generated client.
I can't find how I could, on every request, update the Oauth Token.
There are nothing exposed by feign to do this.
Atm I'm using regular Rest template.
You can used #RequestHeader in feign Client, see below
#FeignClient(name = "<name>", configuration = <configclass>)
public interface Client {
public final String AUTH_TOKEN = "Authorization";
#RequestMapping(method = RequestMethod.GET, value = "users", produces = "application/json")
public HttpEntity<List<User>> getUsers(#RequestHeader(AUTH_TOKEN) String oruToken,
#RequestParam("<param>") Integer value);
}
and from you program you can pass token to feign client
I'm trying to implement a OAuth2 Authorization Server using DotNetOpenAuth. The client is JavaScript based thus incapable of holding any secrets. This is exactly the same problem like this question but with another framework.
The client requests (against the token endpoint) access_token and refresh_token with following parameters:
grant_type: password
username: foo
password: bar
This does work. Now I want use the refresh_token and make a request against the token endpoint with the following parameters:
grant_type: refresh_token
refresh_token: ABCDEF
This gives me the following response:
{"error":"invalid_client","error_description":"The client secret was incorrect."}
Which does make (at least some) sense because RFC6749 states that:
Because refresh tokens are typically long-lasting credentials used to
request additional access tokens, the refresh token is bound to the
client to which it was issued. If the client type is confidential or
the client was issued client credentials (or assigned other
authentication requirements), the client MUST authenticate with the
authorization server as described in Section 3.2.1.
If I change my request like so:
grant_type: refresh_token
refresh_token: ABCDEF
client_id: MYCLIENT
client_secret: CLIENT_SECRET
The problem is my client is not supposed to be confidential (because it is client side JavaScript after all).
This is how the client is defined:
New ClientDescription(ApiKey, New Uri(allowedCallback), ClientType.Public)
I searched through the DotNetOpenAuth source code and found no use of the ClientType. To me it looks like it is not used at all.
It is also not possible to the set an empty client secret, because the DotNetOpenAuth source code actively checkes against this (ClientAuthenticationModules.cs):
if (!string.IsNullOrEmpty(clientSecret)) {
if (client.IsValidClientSecret(clientSecret)) {
return ClientAuthenticationResult.ClientAuthenticated;
} else { // invalid client secret
return ClientAuthenticationResult.ClientAuthenticationRejected;
}
} else { // no client secret provided
return ClientAuthenticationResult.ClientIdNotAuthenticated;
}
If I take a look at MessageValidationBindingElement.cs:
if (authenticatedClientRequest != null) {
string clientIdentifier;
var result = this.clientAuthenticationModule.TryAuthenticateClient(this.AuthServerChannel.AuthorizationServer, authenticatedClientRequest, out clientIdentifier);
switch (result) {
case ClientAuthenticationResult.ClientAuthenticated:
break;
case ClientAuthenticationResult.NoAuthenticationRecognized:
case ClientAuthenticationResult.ClientIdNotAuthenticated:
// The only grant type that allows no client credentials is the resource owner credentials grant.
AuthServerUtilities.TokenEndpointVerify(resourceOwnerPasswordCarrier != null, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
break;
default:
AuthServerUtilities.TokenEndpointVerify(false, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
break;
}
Espacially the comment The only grant type that allows no client credentials is the resource owner credentials grant. makes me wonder. Does that mean that in my scenario the JS client should send username/password along? Nope this will raise the following exception:
AccessTokenResourceOwnerPasswordCredentialsRequest parameter 'grant_type' to have value 'password' but had 'refresh_token' instead.
Which is okay to me, because I don't want the client to keep the password.
So here my questions:
Did I unterstand something fundamentally wrong about the password-grant, refresh_token scheme?
As I see it in a JS client the client_id is public knowledge, so it does not serve any security purpose. Am I correct?
Does it makes sense to change DotNetOpenAuth to make use of the ClientType.Public?
Would it make any difference if I just use client_id and client_secret as not secret? E.g. just supply dummy values? What are the security implications?