Modifying OWIN OAuth middleware to use JWT bearer tokens - c#

I'm currently trying to create a proof of concept for claims based authentication for a new app using a combination of the following technologies: Web API 2, OWIN middleware and JWT.
To keep things simple I started with the Web API 2 project template and changed the authentication to 'Individual User Accounts'. The sample client I created was then able to get a token by calling /Token and was able to call a sample endpoint with the OAuth bearer token. So far so good. I then added the following code to Startup.Auth.cs to try and enable JwtBearerAuthentication:
var jwtOptions = new JwtBearerAuthenticationOptions
{
AllowedAudiences = audiences,
IssuerSecurityTokenProviders = new[] {
new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey) }
};
app.UseJwtBearerAuthentication(jwtOptions);
I expected that Web API 2 would start returning JWTs from the call to /Token, but it doesn't appear to have done anything. I've been banging my head against this for a few days with no success and the Microsoft documents aren't very forthcoming.
I also tried adding the following to my OAuthAuthorizationServerOptions
AuthorizationCodeFormat = new JwtFormat(audience, new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey))
I could also be trying to doing the completely wrong thing.
Any ideas would be greatly appreciated.

Well, now there is a setting on OAuthAuthorizationServerOptions that you can specify the format of your access token, not the authorization code, like you're doing on you example.
So, instead of:
AuthorizationCodeFormat = new JwtFormat(audience, new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey))
You should have:
AccessTokenFormat = new JwtFormat(audience, new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey))

The Windows Identity Foundation uses a proprietary token format, not JWT. The JWT code you see above is for consuming tokens, not generating them. There is a helpful discussion on the ASP.NET forums.
However, in the second half of 2014 Microsoft officially released support for JWT in Windows Identity foundation, with the JSON Web Token Handler. You should be able to install and use that package to solve the problem you have described.

I don't think there's any current way to override how the token is output in the response. I took a look at the OAuthAuthorizationServerHandler in the Katana source code repository.
You'll see that in the InvokeTokenEndpointAsync method, there is a section that creates a JsonTextWriter which generates the response. It is not done in such a way that any kind of extension would affect it.
I find this frustrating too. Microsoft's library should have some way to easily override the response serialization. You can't even add your own custom parameters to the response.

You can use this sample https://github.com/thinktecture/Thinktecture.IdentityModel/tree/master/samples/OAuth2/EmbeddedResourceOwnerFlow
for writting authentication logic in your project.
After it you must add [Authorize] attribute to each controller or action which requires authorization(OWIN Katana contains the logic of validating token, authorization and some other useful things).

Related

PayPal oauth2 authorization and .net core

So I'm trying to set up PayPal sign-in within my .net core application. I'm using this 3rd party library to do so: https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
I'm building my application upon Umbraco CMS, and within the appropriate section I use the following:
builder.AddMemberExternalLogins(logins =>
{
logins.AddMemberLogin(
memberAuthenticationBuilder =>
{
memberAuthenticationBuilder.AddPaypal(
memberAuthenticationBuilder.SchemeForMembers(PayPalMemberExternalLoginProviderOptions.SchemeName),
options =>
{
options.ClientId = clientId;
options.ClientSecret = clientSecret;
});
});
});
Out of the box, this does not work. From reading around it seems that it seems the authorization endpoints are using the live values, and these are not appropriate for testing with Paypal's sandbox endpoints.
After reading the following thread: https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/issues/198 I can see that this user had to update the endpoints manually to use different values:
.AddPaypal(options =>
{
options.ClientId = Startup.Configuration["Authentication:Paypal:ClientId"];
options.ClientSecret = Startup.Configuration["Authentication:Paypal:ClientSecret"];
options.AuthorizationEndpoint = "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize";
options.TokenEndpoint = "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice";
options.UserInformationEndpoint = "https://api.sandbox.paypal.com/v1/identity/openidconnect/userinfo?schema=openid";
})
Now once updating these values, the authorization seems to work. But I've found it to be very unreliable. On my personal dev machine it seems to allow me to authorize, but when testing with another colleague, he finds he is constantly logged out and sometimes it doesn't authorize at all.
When I look at the previous thread I can see that this was written in 2017, and I'm wondering if the endpoints have been updated or the process has been changed entirely by Paypal, but I can't find any documentation on this.
Basically I'm looking for the simplest way to integrate Paypal sign-in on my application. When I read Paypal's documentation (https://developer.paypal.com/docs/log-in-with-paypal/integrate/) I only see mention of refreshing the token, I don't see anything about an authorization endpoint or user information endpoint.
I'm getting quite confused and I'm wondering if anyone has successfully managed to set up a Paypal sign-in with a .net core application in 2022 and whether they have any sample code.
Any pointers would be greatly appreciated. Thanks.
That does seem like an old integration. I would advise following https://developer.paypal.com/docs/log-in-with-paypal/integrate/ from scratch, which can be implemented in any language for the eventual server-side calls. The initial client-side authorization is done in either the JS popup or using a redirect (JS is better)
After exchanging the resulting authorization_code for a refresh token, that token can then be used to obtain information about the user's account (or do API operations involving it), according to the scopes that were authorized.

Identity Server 4 won't use custom Authentication Handler

I have a working AuthenticationHandler<> for MVC Core and it works beautifully. Now I want to re-use the whole thing for Identity Server 4 but the framework seems to work against me.
I have added
builder.Services.AddAuthentication().AddScheme<MyWebsiteOptions, MyWebsiteAuthenticationHandler<TIdentity, MyWebsiteUser>>(CredentialStoreConstants.SCHEMA_NAME, x => { x.ConnectionString = options.ConnectionString; });
And like I said it works 100% for the MVC Core-part. Now, I cannot access IdentityServer4 endpoints like /connect/authorize/callback with it. I have already read the Identity Server 4 documentation over and over again, but somehow I am missing some key thing here.
Does anyone has an idea? I am sure I am not the first person to run into this.
The Identityserver Endpoints are just that, plain endpoints implemented as a middleware for your pipeline.
The relevant files on the Identityserver4 are:
The Middleware: https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Hosting/IdentityServerMiddleware.cs
The Endpoint Router (and its interface): https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Hosting/EndpointRouter.cs
Endpoint Implementation (token endpoint for instance): https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Endpoints/TokenEndpoint.cs
This means they're out of MVC so you can't use your AuthenticationHandler with them
HINT: If you read all the documentation and the answer is not there, its time to dive into the code: https://github.com/IdentityServer/IdentityServer4
Answer. It was more obvious than I imagined it to be.
For the standard .NET Core Authentication, a succesfull pass at AuthenticationHandler<> in not enough
If you have a custom usertype and custom login flow, you also need to do something like this after you succesfully verified the credentials of said custom usertype.
At one point, you need to retrieve the corresponding user from the database and into the rest of the MVC Core authentication flow.
So after something like AuthenticationHandler<>().Succeeded == true you need to do this:
var systemUser = await _userResolver.GetUserAsync(user.Email);
await _signInManager.SignInAsync(systemUser, true);
The last line is the most important as it initializes a correct MVC Core user-session

OpenTok TokBox: REST API access forbidden when starting a live streaming broadcast

Following the procedures outlined in the SDK docs.
Using .NET's WebRequest to make the API call. StatusCode "Forbidden" being returned along with additional message "Invalid issuer format".
What I'm not sure about is how I'm supposed to generate the token for the call. The instructions in the section I linked to simply say:
REST API calls must be authenticated using a custom HTTP header — X-OPENTOK-AUTH — along with a JSON web token. Create the JWT token with the following claims.
This led me to believe I was to use the JWT library of my choice to create the token. So I did. I used .NET's System.IdentityModel.Tokens.Jwt.
In the .NET section of the site, though, this appears:
You can generate a token either by calling an OpenTokSDK.OpenTok instance's GenerateToken... method, or by calling a OpenTokSDK.Session instance's GenerateToken... method after creating it.
Was that what I was supposed to do? Is that what's wrong?
I can include my code but no point if I've taken the wrong approach altogether.
TokBox Developer Evangelist here.
There are two token concepts within the OpenTok API. One of the tokens is used to authenticate an OpenTok Session and the other is a JWT token used to authenticate each HTTP request you make from the server side.
It looks like the token that you're trying to create is used to interact with the OpenTok REST API. Each request you make to the OpenTok REST API has to have a JWT token which is signed by your API Key and API Secret. The signing would look something like this:
var payload = new Dictionary<string, object>
{
{ "iss", "12321312" }, // apiKey
{ "ist", "project" },
{ "iat", now }, // current time
{ "exp", expiry } // current time + 300 seconds
};
You can use the GenerateJWT method in the OpenTok .NET SDK as reference. Alternatively, you can use the OpenTok .NET SDK to make the StartBroadcast request which would handle the JWT token creation for you.
Lastly, to authenticate an OpenTok Session you have to use one of the OpenTok Server SDKs. Please note that tokens used to authenticate OpenTok Sessions are not created by any library.

IdentityServer3 - 401 Unauthorized when calling Identity API Controller

I have a project which uses IdentityServer3 for Auth as a Service.
Recently I was tasked with creating a seamless experience for End-Users to edit their identity information.
I did this by creating an API Controller in my application which uses a HTTPClient to call another API Controller living in my IdentityServer project. It basically exposes the Identity management methods to the world, but "passes-through" any requests on to the IdentityServer Api.
All is well right up until I call the IdentityServer Api Controller. My breakpoint there is never hit, regardless of the presence of a "Authorize" attribute. I end up receiving a "401: Unauthorized" back from the IdentityServer Api controller.
I've tried to reuse the original request's Auth headers, but that didn't work. I also tried to find a "access_token" claim from my claim principle, but one wasn't found.
here is a code snippet:
var httpClient = new HttpClient();
// this didn't work - tried reusing the auth from the original request
//httpClient.DefaultRequestHeaders.Authorization = request.Headers.Authorization;
// this didn't work either - "access_token" is not found
//httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Caller.FindFirst("access_token").Value);
var routePrefix = GetRoutePrefix();
var response = await httpClient.PostAsync(
$"{routePrefix}/post",
new ObjectContent(typeof(TDObj), entity, new JsonMediaTypeFormatter()));
return response;
I'm new to IdentityServer3 and OAuth and not sure what to do next. I tried creating a new scope for "identity" and tried to make it a required scope in my client application, but that didn't seem to do the trick. I know I'm missing some key piece of understanding here, but there is so much documentation for IdentityServer, I don't know where to begin and can't find anything specific to this need. I'm in the weeds! Can anyone help me understand what's going on here? Thanks!
I got it working by following Scott Brady's answer here: Identity Server and web api for user management
However, his answer didn't immediately work for me. I had to make sure to make the call for UseIdentityServerTokenValidation to happen BEFORE api route mapping happened.
That being said, my original attempt to hi-jack the Authorization headers from the inbound HTTPRequest of my Front-End application worked, so I was able to remove any code requesting an access token and didn't have to SetBearerToken() on my HttpClient. Just this:
httpClient.DefaultRequestHeaders.Authorization = request.Headers.Authorization;

OneDrive for business Oauth2 authentication

I am trying to get access to OneDrive for Business using OAuth2.0 authentication protocol. I have followed this example:
http://msdn.microsoft.com/EN-US/library/dn605894(v=office.15).aspx
an this is my code so far:
// Create an authentication context
AuthenticationContext ac = new AuthenticationContext(string.Format("https://login.windows.net/{0}",
ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value));
String id = ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value;
// Create a client credential based on the application id and secret.
ClientCredential clcred = new ClientCredential(AppPrincipalId, AppKey);
// Using the authorization code acquire an access token.
var arAD = ac.AcquireTokenByAuthorizationCode(code, new Uri(appRedirect), clcred);
I am getting a Authorization code is malformed error. I don't understand why I am getting this message.
Any help would be appreciated!
Had the same issue when I was trying to get authorization code manually and then use it from console application. Not sure why it doesn't work for me.
But when I use it from Web App, the same app which performed authorization and received code in return (because I specified it as returnURL) - everything works.
I suggest you to have a look on this example
https://github.com/AzureADSamples/WebApp-WebAPI-OAuth2-UserIdentity-DotNet
And also this article to understand what's happening under the good:
http://blogs.msdn.com/b/exchangedev/archive/2014/03/25/using-oauth2-to-access-calendar-contact-and-mail-api-in-exchange-online-in-office-365.aspx
P.S.
It's not a OneDrive, but I had exactly the same problem, so if you can make it working with Exchange or GraphApi, then it should work for OneDrive as well.
Authorization code is malformed error is occured if you send the auth code in incorrect format. May be the authorization code which you are sending is encoded value of authcode and session state. you need to seperate both values and send the auth code only. or decode the '&' symbol(seperator) between auth code and session state and send them as two parameters.
The method AcquireTokenByAuthorizationCode(...) from ADAL4j takes only authcode.

Categories