Combine ADFS Authentication and JWT Bearer on ASP.Net Application - c#

I have a web API written in ASP.NET and frontend written in Angular. Authentication on the API side can be configured to use either Windows Authentication, ADFS Authentication or JWT Bearer. But for a particular deployment, only one type of authentication is supported.
For the ADFS authentication I am using angular-oauth2-oidc on the Angular side.
On the API side, this is how I am configuring the ADFS authentication in the startup.cs file.
public void ConfigureAuth(IAppBuilder app)
{
app.UseActiveDirectoryFederationServicesBearerAuthentication
(new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
BackchannelCertificateValidator = new CertificateValidator(),
MetadataEndpoint = System.Configuration.ConfigurationManager.AppSettings["ida:ADFSMetadata"],
TokenValidationParameters = new TokenValidationParameters()
{
ValidAudience = System.Configuration.ConfigurationManager.AppSettings["ida:Audience"],
ValidIssuer = System.Configuration.ConfigurationManager.AppSettings["ida:ValidIssuer"]
},
Provider = new OAuthBearerAuthenticationProvider()
{
OnValidateIdentity = async context =>
{
var identity = context.Ticket.Identity;
var emailAddress = identity.FindFirst(ClaimTypes.Email).Value;
using (AuthRepository repo = new AuthRepository())
{
var userManager = repo.GetUserManager();
var aspNetUser = userManager.FindByEmailAsync(emailAddress).GetAwaiter().GetResult();
if (aspNetUser != null)
{
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, aspNetUser.Id));
await ProfileManager.AddClaimsToIdentity(identity, aspNetUser.SelectedProfile);
}
}
}
}
});
}
What I want is to combine ADFS authentication with JWT Bearer in such a way that if the entered email address is associated with my company domain like "email#mycompany.com", it authenticates against the ADFS and if it's any other email, it uses JWT Bearer authentication.
I know different type of authentications can be combined in ASP.NET Core (example here) but my API is not built using the Core.
I have tried to find the same feature for ASP.NET but I couldn't find one. I would like to know if this is possible to achieve and if yes, I will really appreciate if someone can give me a pointer.

On this question:
What I want is to combine ADFS authentication with JWT Bearer in such a way that if the entered email address is associated with my company domain like "email#mycompany.com", it authenticates against the ADFS and if it's any other email, it uses JWT Bearer authentication.
As far as I know, it is possible.
Have you tried Microsoft Identity Platform? This is a specific Azure SDK for managing identities, including support for ADFS 3.0 in Windows Server 2012 and later.
It is also easier to use, because this MIcrosoft Identity Platform is using OpenIDConnect with OAuth 2.0, therefore you can use ADFS that has JWT bearer.
This is the official docs page: https://learn.microsoft.com/en-us/azure/active-directory/develop/
The landing page has various samples for you to get started. Since you are using .NET Core, the Microsoft Identity Platform SDK has sample that you can use is the sample using .NET Core:
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-aspnet-core-webapp
This is a github repo that contains various sample beside that tutorial:
https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2
UPDATE 1:
Current documentation of ADFS in Windows Server 2016 only shows support for OAuth2/OpenIDConnect, and it is using JWT Bearer:
https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/ad-fs-openid-connect-oauth-concepts
I have searched for specific "ADFS Bearer Token Authentication" in the MS official documentation, and it's not available at all. All of the current doc is mentioning about ADFS 3.0 and later (including ADFS in Windows Server 2016 and 2019) is using OAuth2/OpenIDConnect.

Related

Securing API using Identity Server 3 with token created by identity server 4

I am using Identity Server 4 for validating the clients and generating the token. The website is created in Angular with .Net core but the API which was already developed is still in .NET framework 4.7.1 which is not supporting Identity Server 4.
So to protect the API i have configured the API with Identity Server 3 which supports .NET framework 4.7.1 but the issue is it is not validating the token generated by Identity Server 4.
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "http://localhost:5000",
AuthenticationType = "Bearer",
RequiredScopes = new[] { "api_to_be_protected" }
});
is there any way we can validate the token and protect the API from unknown clients which is not authorized and also validates the token created by Identity Server 4
On your identity server, you should set the EmitLegacyResourceAudienceClaim option to true
var identityServerBuilder = services.AddIdentityServer(opt =>
{
opt.EmitLegacyResourceAudienceClaim = true;
});
More information about this property can be found over here: https://identityserver4.readthedocs.io/en/latest/reference/options.html
I also found the nuget package IdentityServer3.Contrib.AccessTokenValidation has a recent update to support IDSrv 4, i would recommend that you use that instead of IdentityServer3.AccessTokenValidation

How to enable facebook authentication in Core .NET 2.2 project?

I have a project written using C# on the top of Asp.NET Core 2.2.
I am using the built-in Identity to enable accounts authentication.
I am now trying to add integration to enable Facebook authentication. I followed the documentation to create an app on Facebook and then enable it on my site. However, every time I try to log in using Facebook, I get the following error
URL Blocked: This redirect failed because the redirect URI is not
whitelisted in the app’s Client OAuth Settings. Make sure Client and
Web OAuth Login are on and add all your app domains as Valid OAuth
Redirect URIs.
In my Facebook account, in the Valid OAuth redirect URIs section I put https://example.com/signin-facebook as you can see in the screenshot below.
What else needed to be done in order to successfully enable Facebook authentication in my website?
Here is how I add the providers
AuthenticationBuilder authBuilder = services.AddAuthentication();
foreach (var provider in providerService.GetAll())
{
if (provider.Name == ExternalLoginProvider.Facebook)
{
authBuilder.AddFacebook(options =>
{
options.AppId = provider.AppId;
options.AppSecret = provider.Secret;
});
}
if (provider.Name == ExternalLoginProvider.Twitter)
{
authBuilder.AddTwitter(options =>
{
options.ConsumerKey = provider.AppId;
options.ConsumerSecret = provider.Secret;
});
}
// other providers
}
Here is a snapshot of my current settings where I added my sie
While you whitelisted https://www.realestatebyareen.com/signin-facebook, are you testing the Facebook login after deploying the app to this URL or locally?
If locally, then you will also need to whitelist the URL where your local application is hosted, most likely something like https://localhost:<some-port>/signin-facebook.

Does IdentityServer4 have API to validate an access token?

I have an Identity Server which is built by using IdentityServer4.
I have 2 applications (1 .NET, 1 PHP) accessing resource each other and using this Identity Server to validate access token in request header.
In Identity Server application I add a client config as below
clients.Add(
new Client
{
ClientId = "myClientId",
ClientName = "My Client Name",
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = new List<string>
{
"php.es.api"
}
});
From .NET application I can get access token easily by calling method RequestClientCredentialsAsync with scope "php.es.api". Then add this bearer token and send request to PHP API.
The problem is I don't know whether IdentityServer4 has API so that PHP application can call it to authenticate the access token. I google and don't find any document mentions about this API.
Do I have to write new API in Identity Server application for PHP or other applications not .NET to validate token?
.NET application access resource from PHP application as below.
There is a standard endpoint for this called the introspection endpoint and it is supported by IdentityServer4. Your best bet is to find an oauth client in PHP that does this. If you are using self-contained bearer tokens you can validate tokens without the need for back-channel communication because the bearer tokens are signed by your provider and your provider has its keys listed in the discovery document required to validate the tokens (/.well-known/openid-configuration). I am not too familiar with PHP to point you in the right direction as to what cool libraries there might be out there

Ws-Federation Identity Information Not Available in Web API?

I'm using Ws-Fed Authentication OWIN middleware to authenticate an ASP.NET MVC app with Web API endpoints using ADFS. I'm able to sign in using ADFS successfully, and on my MVC controllers, HttpContext.User.Identity.IsAuthenticated is true - I can see the claims information for the signed in user as well.
However for WebAPI endpoints, User.Identity.IsAuthenticated is false. The claims information for the signed is user is also unavailable. Is there any way that I expose the fact that the user is authenticated for both MVC and WebAPI controllers?
Here is how I am configuring my authentication middleware in the OWIN Startup class:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
ExpireTimeSpan = TimeSpan.FromMinutes(sessionDuration),
SlidingExpiration = true //expiration extended after each request
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = metadata,
Notifications = new WsFederationAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/?loginfailed=loginfailed");
return Task.FromResult(0);
}
}
});
Try adding a "Name Id" claim to ADFS:
http://darb.io/blog/2014/06/30/WebAPI-and-ADFS-as-external-login-provider/
So I discovered the answer to this question by examining the OWIN cookie authentication middleware source code on CodePlex. Cookies created using the middleware by an MVC controller are created differently from cookies created Web API. MVC cookies are a reference to user information stored in session, and since Web API is completely stateless (no session), cookies created in MVC can not be used in Web API.
In addition, it is bad practice to use cookie authentication in Web API anyways; bearer token authentication is a preferable option.
In my case where I needed to use Ws-Federation authentication, the solution was to:
Add bearer token authentication middleware to my app
Create a Web API endpoint (ideally cryptically named) that will securely receive Ws-Federation claims, perform validation to ensure the request really came from your MVC controller, use them to generate a bearer token, and respond with the generated bearer token
Upon authenticating in MVC, serialize the claims, and marshal them over to Web API using the endpoint created earlier
Add the bearer token to a hidden field in the SPA
Many, many thanks to #Juan for providing me with feedback and links to point me in the right direction.

How to use ASP.net 5 Identity in web API application? User authentication based on tokens. Mobile apps

Assuming that I currently have a newly created project based on Visual Studio 2015 "WebApp" template with Individual Accounts authentication, I use Microsoft.AspNet.Authentication package and I can't always rely on cookies, because my web API should also target mobile apps:
How can I add authentication to my web API? I'm especially interested in token based authentication.
You can use basic http authentication or implement a similar one with a token or ticket passed through http headers.
Implement custom AuthorizeAttribute in your web api project. In IsAuthorized(HttpActionContext actionContext) overload you can check the authorization scheme and authorization header and then you can connect to your sessions provider and check if the user has an active session.
You must pass the login token in the authorization header, so if the token is missing that means there is no active user.
So when you login you must create and encrypt the token on successful login. Then pass this token with each request to the server.
This blog contains more information about using AuthorizeAttribute: http://weblogs.asp.net/jongalloway/asp-net-mvc-authentication-customizing-authentication-and-authorization-the-right-way
You can make separate table in db for storing authentication detail (AuthKey, UserID, CreatedDate, ExpiredDate, IsExpired) and make functions like CheckAuthorizationKey(string authKey), ExtendAuthorization(string authKey), ExpireAuthorization(string authKey){}
and call that functions for checking the authorization as below sample code.
public ServiceResult<LoginModel> Login(string auth_key)
{
var service = new ServiceResult<LoginModel>();
LoginModel user = new LoginModel();
if (AuthKey.CheckAuthorizationKey(auth_key) == false)
{
service.message = TemplateCodes.GetMessage(TemplateCodes.UnAuthorize, null, db);
service.status = ServiceStatus.authorization_failed;
return service;
}

Categories