Authenticating and Authorizing using ADFS WS-Fed protocol - authentication

I am working on implementing Authenticating and Authorization in my application.
For Authentication:
I configured by ADFS Server with WS-Fed Sign in Protocol and enabled JWT. Created MVC application and configured to use WS-Fed for authenticating user.
Now question here is how do I store JWT token in my cookie after successfully login?
Here is my code
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions{ CookieName="JwtToken",CookieHttpOnly=false});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
}
}
For Authorization
I have a separate Web API project. I want to authorize my api's by passing the JWT token in header of every request but not sure how to extract JWT token from cookie and pass it to web api for validating.

I found the answer here http://www.software-architects.com/devblog/2015/02/02/ADFS-and-ADAL-Lab.
ADAL (Active Directory Authentication Libraryfor .NET and for JavaScript) which can be used to acquire token in mvc application and pass the token in header for authorizing web api.

Related

How to Access MVC API which is authorize with IdentityServer4

On Owin middleware Startup class I have added OIDC Authentication where response type is "code id_token". With this middleware I can access my authorized controller. But the problem is, I can't access my API in the same domain with this middleware.
I am using the access_token that i stored in the userClaim. But it is returning the HTML of IdentityServer4 login page.
[Filters.AuthorizeOIDC(Roles = "dukkan.sa")]
public async Task<ActionResult> ViewApiResult()
{
var user = User as System.Security.Claims.ClaimsPrincipal;
var token = user.FindFirst("access_token").Value;
var result = await CallApi(token);
ViewBag.Json = result;
return View();
}
private async Task<string> CallApi(string token)
{
var client = new HttpClient();
client.SetBearerToken(token);
var json = await client.GetStringAsync("http://localhost:57346/api/SampleApi");
return json;
}
The examples I got to secure MVC API is with IdentityServer3. They are using IdentityServer3.AccessTokenValidation package to authenticate the client from back channel during the API Access request:
app.UseOAuthBearerAuthentication(new IdentityServerBearerTokenAuthenticationOptions { Authority = "https://localhost:44319/identity", RequiredScopes = new[] { "sampleApi" } });
But IdentityServer4.AccessTokenValidation is not working with MVC5. I can use IdentityServer3.AccessTokenValidation in MVC 5. But this is accepting IdentityModel with version bellow 2.0.0.
Need solution for it. IdentityServer4 is not supporting properly for MVC.
Why do you want to use IdentityServer4.AccessTokenValidation with MVC5? Because the server is IdentityServer4?
There is no need for that. IdentityServer3 and IdentityServer4 are build on the same OpenId Connect specifications, meaning that you can use IdentityServer3.AccessTokenValidation for the client while the server is IdentityServer4.
In fact you can use any piece of code on the client that is build according to the specifications of OpenId Connect. I suggest you give IdentityServer3.AccessTokenValidation a try.

Authentication and Authorization with ASP.NET Core and Service Stack

I have a ASP.Net Core MVC Web App that users needs to logon to get the id_token from the IdentityServer4 and then that id_token will be passed to webapi implemented in ServiceStack to obtain the authorization code. The subsequent call to the webapi will use the authorization code.
So far what I have read is for the Web App, it should use openid cookie token (UseOpenIdConnectAuthentication). For the webapi, it should use the bearer token. My question is how I can pass that http only cookie token from the client side browser as a bearer token in the http header. As the cookie is http only, it can't be accessed by the Javascript. Moreover, the ASP.NET Core cookie middleware encrypts the cookie, can that encrypted cookie be decrypted by the ServiceStack webapi (if the cookie is passed to the webapi)?
Am I going in the right direction? Any suggestion is welcome.
Thanks
You can find an example of your scenario here: https://identityserver4.readthedocs.io/en/release/quickstarts/5_hybrid_and_api_access.html
The authorization code is only used to get access tokens from the identity server, it is not used to authenticate to APIs.
Here is how the flow should work:
User logs in at Identity Server
Your MVC app gets an authorization code and id token
The id token tells your MVC app who the user is
The authorization code is exchanged for an access token and refresh token with identity server for the API
Now the MVC app can make HTTP calls from its backend using the access token
Authentication cookie is created and returned to user
Front-end submits the authentication cookie with every request to MVC backend, which authenticates every request automatically that hits MVC, then when you want to call the API from there, get it as shown in the docs, and attach it to your requests
I think the point you are missing here is that once the user is logged in, you will get the access token in the response as well when you land back on the client application. If you are using Hybrid Flow, on the client app we configure it as
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "mvc",
ClientSecret = "secret",
ResponseType = "code id_token",
Scope = { "api1", "offline_access" },
GetClaimsFromUserInfoEndpoint = true,
SaveTokens = true
});
See the ResponseType we ask for code i.e the access code. So you need not to call or login again. Once you want to call your api just get the token like
var access_token = await HttpContext.Authentication.GetTokenAsync("access_token");
// call api
var client = new HttpClient();
client.SetBearerToken(access_token);
var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
And if you using Implicit flow, your front end can get the access token using oidc-client library and user.access_token will have it.

Asp.net mvc web use both token base authentication and form authentication

I have an asp.net mvc project that contains some web API controllers.my mvc area and pages are authenticated via form authentication.
API controllers should be consumed from native android client I need to register deice and authenticate them for some API's. I searched and seen some web api example used token authentication but here how can i merged both token and form authentication for different request?
how can i customize my security configuration to generate token and authenticate api requests?
here is Startup.Auth class:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager> (ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}

Using ASP.NET MVC 6 Web API Identity when I have a token from FB

I'm using FB SDK for iOS to login my users. My understanding is that I can get a granted token from SDK on the client side and use it to authenticate users in my Web API. What I can't understand is how to use SignInManager<ApplicationUser> to authenticate my users only with a token.
You need JWT Bearer authentication.
Facebook grants you an access_token in JSON Web Token (JWT) format. Include that as a bearer token in your Web API requests.
GET http://www.webapi.com/v1/people
Authorization: Bearer the_facebook_access_token_goes_here
Then use the ASP.NET Security JWT bearer middleware. It will read the token and populate the HttpContext.User.Identity.
The ASP.NET team has a sample here: https://github.com/aspnet/Security/tree/dev/samples/JwtBearerSample Here are the fundamentals of how to configure JWT Bearer authentication.
project.json
dependencies : {
"Microsoft.AspNetCore.Authentication.JwtBearer": "1.1.0-*",
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
}
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
// set these to the Facebook Authority and Audience
Authority = ""
Audience = ""
});
Decorate your Web API actions with the [Authorize] attribute.
That might be enough to get you started.

OWIN Cookie authentication in Self-Hosted Web Api

I have an OWIN Self-hosted Web Api and some MVC web applications all in the same domain. Web applications are calling the Web Api in server side. They use OWIN cookie authentication like this:
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity =
SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser, Guid>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) =>
user.GenerateUserIdentityAsync(manager),
getUserIdCallback: (id) => (new Guid(id.GetUserId())))
}
});
}
Being in the same domain, when user sign in one web application, the cookies are available in other web applications and the user is signed in.
I implement cookie authentication in my self-hosted web api like this:
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.MessageHandlers.AddRange(new List<DelegatingHandler>
{
new ServerContextInitializerHandler(), new LogRequestAndResponseHandler(),
});
config.MessageHandlers.AddRange(ServiceLocator.Current.GetAllInstances<DelegatingHandler>());
config.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
Provider = new CookieAuthenticationProvider(),
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active
});
appBuilder.UseWebApi(config);
}
I expect to have the user in web api, as it's in the same domain and the cookies are all available in received requests.
The problem is the Request.GetRequestContext().Principal is null (and other alternatives like Request.GetOwinContext().Authentication.User).
I emphasis that the Request.GetOwinContext().Request.Cookies contains all cookies that are available in the web application.
It has passed a long time from asking the question, but there is no answer yet, but I found the reason and I'm just sharing it. Hope to be useful.
As I mentioned, I implemented cookie authentication in my self-hosted web api, and the authentication cookie was available in the received request in web api.
The problem is, In web applications (where the users signed in) OWIN middle-ware is encoding the ClaimsIdentity data into an Access Token and put it in the authentication cookie, and to access the authentication data in this cookie, decode it's content. This encoding and decoding on web applications is done by encryption and decryption using Machine Key of the machine on which the server is running, and in self hosted web api using another way named DPAPI.
So, I had the authentication cookie on web api request, but because the OWIN middle-ware tried to do decryption using DPAPI, it wasn't able to extract the Access Token from the cookie.