Cant get simple Oauth wth vertx to work with google - oauth

Trying to create a web client that uses oauth to connect to multiple sso endopints, google mainly. This is on top of a spring boot project, I just keep getting the same error that no code is provided, but I'm not sure how i'm supposed to get a code without the access token first. Here is a simple version of what im trying to run I want localhost/8080 to redir to google to login and comeback to the same page or a different one doesn't matter
#RequestMapping("/google")
fun google(#RequestParam(value = "code") code: String?, model: Model): String {
val clientId = "asdf.apps.googleusercontent.com"
val secret = "1234"
var goog = GoogleAuth.create(Vertx.factory.vertx(), clientId, secret)
goog.authenticate(JsonObject().put("code", code), {
System.out.println(it)
})
return "test"
}
the error is always
"error": "invalid_request",
"error_description": "Missing required parameter: code"
}}
e```
but how can I provide a code first I need some sort of response from the server. I'm pretty familiar with restful oauth and must be missing something

You can't use the GoogleAuth like that. GoogleAuth provides the basic primitives to handle the OAuth2 protocol. As you're not using the vertx-web part you will need to setup a callback endpoint in your application (I guess it's the /google endpoint you listed) but now you miss the whole Oauth2 handshake. Your client (browser) should call Google, which calls your server to validate the code.
So what you're asking here is to re-implement the vert.x web Oauth2Handler using Spring Boot APIs.

Related

Issue authenticating to Auth0 via Swagger UI (.NET) with client credentials

I'm trying to authenticate to my Auth0 tenant via the Swagger UI (auto-generated by Swashbuckle.AspNetCore) using client credentials.
I'm getting the following error:
Auth ErrorError, error: access_denied, description: Non-global clients
are not allowed access to APIv1
Here's a screen shot:
Open API spec looks like this:
"securitySchemes": {
"auth0": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://example.auth0.com/oauth/token"
},
"authorizationCode": {
"authorizationUrl": "https://example.auth0.com/authorize?audience=test",
"tokenUrl": "https://example.auth0.com/oauth/token",
"scopes": { }
}
}
}
}
I suspect this has something to do with the audience not being specified. I was having a similar issue with authorization code flow, but manged to get this working by appending the audience as a query-string param to the authorizationUrl (as shown above). Unfortunately the same trick doesn't work with client credential flow (i.e. attempting to append the audience to the tokenUrl). I need to support client credential flow, as one or more of the routes need to be locked down to M2M tokens only.
Interestingly, it works if I use the global client ID / secret (found under the advanced settings of the tenant), but I'm not sure if we should use this...
Anyone else ran into this issue and if so, any luck with finding a solution?

Getting Group Claims With ADFS 4.0 OAuth2 Token

I successfully set up an ADFS 4.0 instance (Windows Server 2016) which I intend to use to authenticate and authorize the users of a single-page application towards a WebApi.
I pretty much followed this tutorial: https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/single-page-application-with-ad-fs .. which is modifying a sample that uses Azure Active Directory.
Now.. all seems to work fine, I can get a basic JWT token from the /oauth2/authorize endpoint:
{
"aud": "d668d637-7fd4-45ef-9eab-46fee230dcbc",
"iss": "https://fs.contoso.com/adfs",
"iat": 1494341035,
"exp": 1494344635,
"auth_time": 1494341035,
"nonce": "c91e3f78-c31a-402e-a685-8d1586915227",
"sub": "Rl7sOj0nDbgh8BVWZegrkvgAKaB/SwNuEbmORcWcae4=",
"upn": "john.doe#contoso.com",
"unique_name": "CONTOSO\\JohnDoe"
}
The token from AzureAD contained more properties, particularly family_name and given_name. But I was also hoping to add explicit group claims to the token. I thought I should be able to make this happen by setting the 'Issuance Transform Rules' correctly in the Web application Properties ( Application Groups -> MyApp -> MyApp - WebApplication -> Properties). However, it seems no matter what I do, nothing seems to have any effect on the properties contained in the JWT returned from the endpoint. I always get exactly the same token structure.
I am not really sure how the 'Outgoing Claims' map to the token properties as nothing except the 'UPN' and the 'unique name' seems to be transferred. Any pointers what I may be doing wrong here?
As indicated in nzpcmad's answer, it appears that custom claims in the id_token using the default URL-parameter-encoded GET redirect is simply not supported. The reason for this may be that there is an URL length limit, but I find that quite questionable.
Anyway, apparently this restriction does not apply when the token is returned in a POST redirect. That's also why people describe it working just fine for MVC applications.
So I was able to work around the problem by redirecting the response to a backend API endpoint (POST), which just redirects it to the frontend (SPA) again, but as a GET request with URL-endcoded parameters:
public class LoginController : ApiController
{
[HttpPost]
[Route("login")]
public HttpResponseMessage Login(FormDataCollection formData)
{
var token = formData["id_token"];
var state = formData["state"];
var response = Request.CreateResponse(HttpStatusCode.Moved);
var frontendUri = ConfigurationManager.AppSettings["ad:FrontendUri"];
response.Headers.Location = new Uri($"{frontendUri}#id_token={token}&state={state}");
return response;
}
}
Note that to change the response method from GET to POST, one simply has to add &response_mode=form_post to the OAuth request URL.
Windows Server 2016 is ADFS 4.0.
SPA uses OAuth implicit flow and there are a number of posts around this suggesting that this flow doesn't allow extra claims, especially if you are using ADAL.
e.g. ADFS 4.0, Adal JS - No claims.

Microsoft Graph API access token validation failure

I use this URL to get id_token:
https://login.microsoftonline.com/common/oauth2/authorize?
response_type=id_token%20code&
client_id=MY_CLIENT_GUID_ID_IN_HERE&
redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fopenid%2Freturn&nonce=alfaYYCTxBK8oypM&
state=6DnAi0%2FICAWaH14e
and this return result like this
http://localhost:3000/auth/openid/return?
code=AAA_code_in_here&
id_token=eyJ0eXAi_xxxx_yyyy_in_here&
state=6DnAi0%2FICAWaH14e&
session_state=xxxx_guid_xxxxx
and then i use the id_token to query Graph (use POST man)
i have see this post InvalidAuthenticationToken and CompactToken issues - Microsoft Graph using PHP Curl but make no sense.
OATH 2.0 requires multiple steps. The first request returns an OAUTH Code. The next step is converting that OATUH code into a Bearer Token. This is the step you are missing here.
I would also recommend using the v2 Endpoint which is a lot easier to work with (particularly with Graph). I wrote a v2 Endpoint Primer that walks through the process and may be helpful as well.
You can't use the token directly, there is one more step to exchange the code you get from the response url into token.
Here is my C# code (using Microsoft.IdentityModel.Clients.ActiveDirectory)
public static AuthenticationResult ExchangeCodeForToken(string InTenantName, string InUserObjId, string InRedirectUri, string InApplicationAzureClientID, string InApplicationAzureClientAppKey)
{
Check.Require(!string.IsNullOrEmpty(InTenantName), "InTenantName must be provided");
Check.Require(!string.IsNullOrEmpty(InUserObjId), "InUserObjId must be provided");
if (CanCompleteSignIn) //redirect from sign-in
{
var clientCredential = new ClientCredential(InApplicationAzureClientID, InApplicationAzureClientAppKey);
var authContext = new AuthenticationContext(Globals.GetLoginAuthority(InTenantName), (TokenCache)new ADALTokenCache(InUserObjId)); //Login Authority is https://login.microsoftonline.com/TenantName
return authContext.AcquireTokenByAuthorizationCode(VerificationCode, new Uri(InRedirectUri), clientCredential, Globals.AZURE_GRAPH_API_RESOURCE_ID); //RESOURCE_ID is "https://graph.microsoft.com/"
}
return null;
}
I had this issue today when I was playing with graph API, the problem in my case was how I was generating the token.
I used postman for generating the token wherein the Auth URL section I was adding the resource = client_id whereas it should be the graph URL. After making that change I was able to make the call via postman.
In order for the above to work, please make sure your application in Azure has delegated permissions to access the Graph API.
To receive the access token and use it for profile requests, you don't need anything from server-side, you can implement the oAuth2 just from the client side.
Use the following URL for login:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=YOUR_CLIENT_ID&resource=https://graph.microsoft.com&response_type=token&redirect_uri=YOUR_REDIRECT_URI&scope=User.ReadBasic.All
After successful login, user will redirected to the page with access_token parameter. Then use the following AJAX call to fetch user info:
var token = login_window.location.href.split('access_token=').pop().split('&')[0];
$.ajax({
url: "https://graph.microsoft.com/v1.0/me",
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Bearer '+token);},
success: function(data) {
alert('Hi '+data.displayName);
console.log(data);
}
});
Note that you may need to enable oauth2AllowImplicitFlow:true setting from your Azure Active Directory application manifest file.
Set "oauth2AllowImplicitFlow": false to "oauth2AllowImplicitFlow": true.
Lastly, ensure that your app has required permissions for Microsoft Graph which are sign in users and View users' basic profile
An updated answer to get access with new applications:
Register your app in the app registration portal.
Authorization request example:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345
Authorization response will look like this:
https://localhost/myapp/?code=M0ab92efe-b6fd-df08-87dc-2c6500a7f84d&state=12345
Get a token
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps
Use the access token to call Microsoft Graph
GET https://graph.microsoft.com/v1.0/me
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: graph.microsoft.com
Source:
https://learn.microsoft.com/en-us/graph/auth-v2-user?context=graph/api/1.0
You can also get an access token without a user, see here:
https://learn.microsoft.com/en-us/graph/auth-v2-service

OWIN middleware for OpenID Connect - Code flow ( Flow type - AuthorizationCode) documentation?

In my implementation I am using OpenID-Connect Server (Identity Server v3+) to authenticate Asp.net MVC 5 app (with AngularJS front-end)
I am planning to use OID Code flow (with Scope Open_ID) to authenticate the client (RP). For the OpenID connect middle-ware, I am using OWIN (Katana Project) components.
Before the implementation, I want to understand back-channel token request, refresh token request process, etc using OWIN.. But I am unable to find any documentation for this type of implementation (most of the available examples use Implicit flow).
I could find samples for generic Code flow implementation for ID Server v3 here https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source
I am looking for a similar one using OWIN middleware ? Does anyone have any pointers ?
Edit: good news, code flow and response_mode=query support was finally added to Katana, as part of the 4.1 release (that shipped in November 2019): https://github.com/aspnet/AspNetKatana/wiki/Roadmap#410-release-november-2019.
The OpenID Connect middleware doesn't support the code flow: http://katanaproject.codeplex.com/workitem/247 (it's already fixed in the ASP.NET 5 version, though).
Actually, only the implicit flow (id_token) is officially supported, and you have to use the response_mode=form_post extension. Trying to use the authorization code flow will simply result in an exception being thrown during the callback, because it won't be able to extract the (missing) id_token from the authentication response.
Though not directly supported, you can also use the hybrid flow (code + id_token (+ token)), but it's up to you to implement the token request part. You can see https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/dev/samples/Nancy/Nancy.Client/Startup.cs#L82-L115 for an example.
The answer and comment replies by Pinpoint are spot on. Thanks!
But if you are willing to step away from the NuGet package and instead run modified source code for Microsoft.Owin.Security.OpenIdConnect you can get code (code) flow with form_post.
Of course this can be said for all open source project problems but this was an quick solution for a big thing in my case so I thought I'd share that it could be an option.
I downloaded code from https://github.com/aspnet/AspNetKatana, added the csproj to my solution and removed lines from https://github.com/aspnet/AspNetKatana/blob/dev/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs in AuthenticateCoreAsync().
You must then combine it with backchannel calls and then create your own new ClaimsIdentity() to set as the notification.AuthenticationTicket.
// Install-Package IdentityModel to handle the backchannel calls in a nicer fashion
AuthorizationCodeReceived = async notification =>
{
var configuration = await notification.Options.ConfigurationManager
.GetConfigurationAsync(notification.Request.CallCancelled);
var tokenClient = new TokenClient(configuration.TokenEndpoint,
notification.Options.ClientId, notification.Options.ClientSecret,
AuthenticationStyle.PostValues);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(
notification.ProtocolMessage.Code,
"http://localhost:53004/signin-oidc",
cancellationToken: notification.Request.CallCancelled);
if (tokenResponse.IsError
|| string.IsNullOrWhiteSpace(tokenResponse.AccessToken)
|| string.IsNullOrWhiteSpace(tokenResponse.RefreshToken))
{
notification.HandleResponse();
notification.Response.Write("Error retrieving tokens.");
return;
}
var userInfoClient = new UserInfoClient(configuration.UserInfoEndpoint);
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
if (userInfoResponse.IsError)
{
notification.HandleResponse();
notification.Response.Write("Error retrieving user info.");
return;
}
..

Apache Oltu Spring Security OAuth2 and Google Integration

The reference being purely taken from following sites:-
http://syntx.io/integrating-your-java-spring-mvc-webapp-with-facebook-doing-the-oauth-dance/
http://www.oodlestechnologies.com/blogs/OAuth-2.0-implementation-in-Spring-Framework
I've developed String Security OAuth2 Facebook integration example, Now I'm looking forward to developed the Security OAuth2 Google (and later Github) integration example where AppID and Secret will be provided to get "access_token" and "refresh_token" etc to be used to access the protected resources like UserDetails etc..
So, first step will be register App on http://code.google.com/apis/console. So it gives me "Client ID" and "Client secret", also I've configured Redirect URI, Done !
Now I've started writing actual Apache OAuth client, but I'm not sure what parameters I need to provide (similarly I provide for Facebook Integration, those parameters were easily available on facebook,while doing google search, but not found for Google), Please provide me suggestions what values should be given for the following blank parameters -
I think I've provided enough information, so any guidance / help / links is appreciated.
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation("")
.setClientId("3kT21Hlkzzt5eV1")
.setRedirectURI("http://localhost:8080/apache-oltu/google/redirect")
.setResponseType("")
.setScope("")
.buildQueryMessage();
The following code is developed for callback
private void getAccessToken(String authorizationCode) throws OAuthSystemException, OAuthProblemException {
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("")
.setGrantType()
.setClientId("3kT21H5EO3zzt5eV1")
.setClientSecret("1kT21Hdlkzzt5eV1")
.setRedirectURI("http://localhost:8080/apache-oltu/google/redirect")
.setCode()
.buildBodyMessage();
Added the following code to get protected resources like user profile:
request= new OAuthBearerClientRequest("https://www.googleapis.com/auth/userinfo.profile").
setAccessToken(oAuthResponse.getAccessToken()).
buildQueryMessage();
See here for a complete example:
http://mail-archives.apache.org/mod_mbox/oltu-user/201503.mbox/%3CA562FE5D3662044186474F4174F11DAE13044C639F#iowajhnex126.iowa.gov.state.ia.us%3E
I've developed Apache Oltu and Spring integration example and it's working fine at my end.
You need to enable the Google+ API as suggested by #prtk_shah. Thanks.
You need to go to the https://console.developers.google.com/project?authuser=0 and click on your project, in my case it's "apache-oltu", in your open project find option "APIs and auth" --> APIs. search for Google+ API and enable it.
Here you should be able to see this screen.
So, I will modify your code below it should be like this:
(IMP) - Your client ID should be like this, For Ex: (755670439314-jcumfghnkmcm72hf40beikvoatknstml.apps.googleusercontent.com), Please make sure it is correct. Fyi - use as it is provided by google developer console
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation("https://accounts.google.com/o/oauth2/auth")
.setClientId("3kT21Hlkzzt5eV1.apps.googleusercontent.com")
.setRedirectURI("Give your projects redirect URI")
.setResponseType("responsecode")
.setScope("openId profile email")
.buildQueryMessage();
The callback code should be:
private void getAccessToken(String authorizationCode) throws OAuthSystemException, OAuthProblemException {
OAuthClientRequest request = OAuthClientRequest
.tokenLocation("https://accounts.google.com/o/oauth2/token")
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId("give your complete client id")
.setClientSecret("give your secret")
.setRedirectURI("This will be your callback or Redirect URL (Give it correctly)")
.setCode(authorizationCode)
.buildBodyMessage();
Here is what I'm getting in my example, just wanted to show you
Hope this will be helpful.

Resources