Web API 2.0 Owin authorization with multiple .net applications - c#

I have two .net applications.
Both applications have WebAPI 2.O APIs using C#.
Let's say one is parent application another one is a child.
Parent application has Owin authentication and all APIs working as expected with Authorization.
In child application, I want to use same Authorization provider used in the parent application. I don't want to use authentication for child application again.
Two things I have tried:
Use of same machine keys in both the applications
Tried to create a third independent .net application which will provide authentication and authorization for both the applications.
First one didn't work. I am not sure how I can achieve the second one.
Any help would be appreciated.
Thanks.

So, if I understood correctly, you want a way to authenticate a child service, based on the parent service authentication passing authentication between the services.
We just need the same thing here, to authenticate the microservices behind our front service (parent service).
We used JWT for that, using it we can solve that, because on the child services (in our case microservices) they trust the parent authentication.
The services work like this, the Parent Service or maybe another Authentication service creates the valid JWT to be used on the Parent Service.
When the Parent Service, receveives the JWT they will validate everything that's need to ensure the client is corret. When the Parent Service need to call the Child Service, it'll send the same JWT, but on the Child Service the JWT will be not the same, in our case we just validate the Lifetime and Issuer Sign Key.
We end up with a code like this on our Startup.cs file on our child services, our parent service/auth service was kept the same.
public static void ConfigureAuth(IServiceCollection services)
{
services
.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.SaveToken = true;
o.TokenValidationParameters = new TokenValidationParameters
{
// Must validate the signing key
ValidateIssuerSigningKey = true,
// Must validate the life time
ValidateLifetime = true,
// The issuer may vary in a multitenant scenario,
// that's why we not valid the issuer.
ValidateIssuer = false,
ValidIssuer = o.ClaimsIssuer,
// Allowing passing a token among multiple services (audiences).
ValidateAudience = false,
ValidAudience = "",
// Does not require expiration
RequireExpirationTime = false,
ClockSkew = TimeSpan.Zero
};
});
}
If you still have doubts I recommend you to look for Authentication Between Microservice, maybe that can help.

Store the generated authentication token (along with user identity info if needed) from the Parent application in a secure Redis cache.
You can then get the token from subsequent requests on the Parent API's authorized endpoints, and append it on any calls to your Child API:
public class ValuesController : ApiController
{
[Authorize]
public IHttpActionResult Get()
{
var authToken = Request.Headers.Authorization;
// send authToken with requests to child endpoints
}
}
Then on the Child API you can get the auth token in a similar manner, and lookup & validate it against the stored Redis tokens.
Extra points if you're getting the token in middleware.

Related

How to authenticate azure functions with firebase auth

Before I explain my problem I want to share some insights about what I am trying to do. I am developing a serverless application in Azure. My azure app service plan contains multiple azure function application and each function app contains multiple azure functions(HTTP triggers/API) in it. Now I want to authenticate all the serverless API. I am using firebase to authenticate my users. How I can achieve it in a minimal and reusable manner.
I already use firebase in asp.net core for authentication in a monolithic manner but for a situation like this, I am not sure How to do.
In a Monolithic manner. In our ConfigureServices method, we need to register the services necessary to handle authentication and to specify the parameters of our Firebase project.
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://securetoken.google.com/my-firebase-project";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://securetoken.google.com/my-firebase-project",
ValidateAudience = true,
ValidAudience = "my-firebase-project",
ValidateLifetime = true
};
});
Then in our Configure method, we have to do one simple call to register the actual middleware that will handle the authentication.
app.UseAuthentication();

Web API Validate JWT Bearer Token from Custom Auth Provider

I've been looking for an example or tutorial for a few hours and thought I should post something at this point.
I'm trying to validate a bearer token from a custom Auth provider inside my .Net 4.7.2 Web Api 2 project. I have a SPA app that gets a bearer token from this auth provider, and sends the bearer token to my WebApi endpoints. I need to turn around and validate the token in each request. I thought there would be a way to point the classes in the Microsoft.Owin.Security.Jwt namespace to validate the token based on the auth providers well known discovery information url.
Has anyone done this before or point me towards a good library/documentation/tutorial?
I know I can write my own auth request filter and go out and pull down the public certificate from the auth server and parse the token and validate the signature, but it seems like a horrible idea for me to write that myself vs using the appropriate libraries.
Ok turns out I found a good example here
The following code sets up our webapi to validate tokens with our custom auth provider while discovering the public key through the OIDC discovery url.
var issuer = "https://my-auth-provider-here/";
IConfigurationManager<OpenIdConnectConfiguration> configurationManager =
new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;
appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions()
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
AuthenticationType = "Bearer",
ValidIssuer = issuer,
ValidateAudience = false,
IssuerSigningKeys = openIdConfig.SigningKeys
}
});

ValidateIssuer option in OpenID connect authentication

We are using OIDC library and for now we allow only MSA account login. So we have configured parameters ValidateIssuer = true and Validissuers = https://login.microsoftonline.com/..” However, we now need to onboard other AAD tenants (for example : abc#dell.com) to our application so we decided to set ValidateIssuer = false.
Since my application is already backed up by custom authorization, I am finding it difficult to understand the purpose of this flag altogether. Basically my question is under what circumstances one would not like to set this flag to false ? And what risk one might ran into if set to false ?
I looked at AAD docs published here and still not able to find convincing response from the comments over sample code snippet :
// ValidateIssuer set to false to allow work accounts from any organization to sign in to your application
// To only allow users from a single organizations, set ValidateIssuer to true and 'tenant' setting in web.config to the tenant name or Id (example: contoso.onmicrosoft.com)
// To allow users from only a list of specific organizations, set ValidateIssuer to true and use ValidIssuers parameter
TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false
},
As the other answer already mentioned, if you leave ValidateIssuer = false, then OIDC middleware will not try to validate the issuer tenant and it would effectively mean that your application is open for anyone with a user in Azure AD.
Some suggestions on tackling multi-tenant case
If you know the list of valid issuers ahead of time, make use of a list of issuers in TokenValidationParameters.ValidIssuers.
Example:
ValidIssuers = new List<string>()
{
"https://sts.windows.net/6d9c0c36-c30e-442b-b60a-ca22d8994d14/",
"https://sts.windows.net/f69b5f46-9a0d-4a5c-9e25-54e42bbbd4c3/",
"https://sts.windows.net/fb674642-8965-493d-beee-2703caa74f9a/"
}
If valid issuers for your application are dynamic or if you want to write some logic to gather that list, you can write an implementation for TokenValidationParameters.IssuerValidator which has your custom logic. You just need to set a delegate that will be used to validate the issuer.
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
// Set this to a delegate and write your own custom implementation there. See code sample URL ahead for more details.
IssuerValidator = AadIssuerValidator.ValidateAadIssuer
};
If neither case makes sense, and your validation logic is unrelated to the tenant to which caller belongs, set TokenValidationParameters.ValidateIssuer to false, but make sure you add your custom logic at the end for example in SecurityTokenValidated notifications.
Sample Code
Build a multi-tenant SaaS web application using Azure AD & OpenID Connect
Look closely at these files in this sample:
App_Start/Startup.Auth.cs
Utils/AadIssuerValidator.cs
This flag allows the OpenID Connect authentication handler to make sure the person who logs in to your application comes from a known AAD tenant. If you set it to false, this validation doesn't happen. What it effectively means is that anyone accessing your application and logging in successfully when being redirected to AAD will be allowed in your application.
In summary, I'd say the only two circumstances you want to set this flag to false are if:
you don't know in advance which tenants can connect to your application; or
you want to allow people from every single AAD tenant to connect to your application.
Also, I'd be curious to know what you mean by "the application is already backed up by custom authorization".
Cheers

Web Api OWIN - How to validate token on each request

I have two applications
Client application build on ASP.NET MVC
Authentication server build on Web API + OWIN
Have planned authentication as follow
For user login client app will make a request to authication server with logged in credential.
Authication server will generate a token and will send back to client application.
Client application will store that token in local storage.
for each subsequent request client app will attached token kept in local storage in request header.
NOW, ON SERVER SIDE OF CLEINT APP I NEED TO VALIDATE THAT TOKEN COMES WITH EACH REQUEST IS NOT TEMPERED.
Please suggest me how to validate token in each request as i don't know the key the OWIN has used to generate the token.
Is is right to write code to validate token on client app or it should be on authication server.
I am planning to shift all user management code like register user, change password to authentication server so than we can re-use it for different client app- is it right design practice?
So far i have wrote below code to just to create a POC.
=========================OWIN configuration========
[assembly: OwinStartup(typeof(WebApi.App_Start.Startup))]
namespace WebApi.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new
OAuthBearerAuthenticationOptions());
}
}
}
==============================oAuth Provided========================
public class SimpleAuthorizationServerProvider: OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
Please help,
Thanks,
#Paul
Please suggest me how to validate token in each request as i don't
know the key the OWIN has used to generate the token.
Your current setup, were you have added the app.UseOAuthBearerAuthentication() to the owin pipeline, will authenticate the user from the bearer token which is passed on each request for you.
The current user can then be found via HttpContext.Current.User.
Use the Authorize attribute to then decide which users are authorized on certain endpoints.
Here's an example where users with the role "user" are allowed to access
[Authorize(Roles="user")]
public class ValuesController : ApiController
{
}
Is is right to write code to validate token on client app or it should
be on authication server.
NO, you don't validate the token in client, if your user credentials are wrong you wont get a token at all. That's all you need to know.
And also, why should you want to validate the token in the client?
I am planning to shift all user management code like register user,
change password to authentication server so than we can re-use it for
different client app- is it right design practice?
Reusing a token provider is common. Why invent the wheel for every application? Build one great, or use a third party, and reuse it across your applications.
Use JSON Web Tokens (JWT) and claims identities, not random tokens that require keeping track of the issued tokens.
A JWT is like a passport issued by a trusted authority. The passport is signed/stamped, and you can verify that it was issued by this trusted authority and that it has not been tampered with. That means, the integrity of the access-right claim present in the token can be verified without keeping state anywhere. The only communication that needs to happen between the trusting application and the authority is an initial (secure) download of the authority's public key (used for signing the tokens).
It's also advisable that you use a standard claims schema, like OpenID Connect ( http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims )
A good book on the topic, which helped me a lot getting an understanding of all these concepts, can be found here: A Guide to Claims-Based Identity and Access Control.
One way to verify a token has not been tampered is to sign it using an asymmetric key pair, Identity Server uses this approach as seen here.
In your case if you are rolling your own authentication you will need to implement this yourself, and check on every request probably in a custom middleware that the token is valid.
If you create, sendback, save in localStorage and every thing about JWT Token as correct, you have to know that many ways are in .Net that you can to controlling per request.
Server side controlling:
If you are using Web API Core, in core you can create Middleware that runs as pipline in run time, and you can give context and check token that requested, for more infomation check: This.
If you use of Asp.net MVC, you can use ActionFilter in MVC(Asp.Net-Core have more advance ActionFilter too), that each requests goes through on and you can check every thisng abount request, for more information check: This.
ClientSide Conftolling:
After that you give Token after log in from server side, you have to save data in localstorage that your browser check per request that data, they advantage are the Expireation and every like this issue in token save in localstorage and you and browser can use of this for more information check: This.
GoodLuck.

Azure AD 401 error - Authenticating from angular client

I have a separate angular client that I want to authenticate to using Azure AD. I am using ADAL JS and all of that seems to be working fine. I get redirected to the AD login page, and then sent back to my application. I can see the token getting passed with each subsequent http request.
However, when I try to make a secured request to my Web API I receive a 401 Unauthorized error. I am loosely following the guide here for setup. I say loosely because I'm not using MVC, my client is in a separate codebase entirely.
I am positive that my user has access to this application.
My Auth Configuration stuff looks like:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(new WindowsAzureActiveDirectoryBearerAuthenticationOptions()
{
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = ConfigurationManager.AppSettings["AzureADAudience"],
},
Tenant = ConfigurationManager.AppSettings["AzureADTenant"],
AuthenticationType = "OAuth2Bearer"
});
Audience: https://login.windows.net/xyz.onmicrosoft.com/myappname
Tenant: xyz.onmicrosoft.com
The controller I'm locking down is decorated like this:
[HostAuthentication("OAuth2Bearer")]
[Authorize]
[RoutePrefix("Auth")]
Is your SPA hosted with your backend? If so, then you need to change your audience to the Client ID.
ValidAudience = ConfigurationManager.AppSettings["ida:ClientID"]

Categories