I'm trying to use the same authentication between the MVC controllers and the Web Api controllers. The Web api is in the same project, just in an /Controllers/API/ folder.
I can't seem to figure out how to authenticate using OWIN, when I logged in through MVC and created a claim and a cookie like the example below.
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name,"Admin"),
new Claim(ClaimTypes.Role,"Administrator")
, "ApplicationCookie");
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
authManager.SignIn(identity);
return RedirectToAction("Index", "Home", null);
}
Everything works fine in the MVC controllers, but I can't use the [Authorize(Roles="Administrator"] attribute on my web API controller and have it work correctly. It always lets me through regardless.
Thanks
EDIT: Only way I've been able to combat this is having a static class and property store the IPrincipal and then when Overriding the Authorize Attribute, look for that property and check if the Role is there that way. Which im not sure if that is a good idea or not?
Where is your authentication code written ? MVC Controller or Web API Controller ? I would recommend to have it in your web API controller that way you can later use it for any other application (SPA or any other web application).You need to build a Authorization server/Resource Server model (sorry for my english wasn't sure how to frame this sentence). In your case Web API being both and MVC site being a resource server.
Below is a sample for JWT + Cookie middleware
Build a authorization server using JWT with WEB API and ASP.Net Identity as explained here http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/
once you do that your webAPIs startup.cs will look like below
/// Configures cookie auth for web apps and JWT for SPA,Mobile apps
private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
//Cookie for old school MVC application
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
CookieHttpOnly = true, // JavaScript should use the Bearer
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/api/Account/Login"),
CookieName = "AuthCookie"
};
// Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
app.UseCookieAuthentication(new CookieAuthenticationOptions());
OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(ConfigurationManager.AppSettings["JWTPath"])
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
You can find CustomOAuthProvider,CustomJwtFormat classes here https://github.com/tjoudeh/AspNetIdentity.WebApi/tree/master/AspNetIdentity.WebApi/Providers
In your MVC app add below in startup.cs
public void Configuration(IAppBuilder app)
{
ConfigureOAuthTokenConsumption(app);
}
private void ConfigureOAuthTokenConsumption(IAppBuilder app)
{
var issuer = ConfigurationManager.AppSettings["AuthIssuer"];
string audienceid = ConfigurationManager.AppSettings["AudienceId"];
byte[] audiencesecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["AudienceSecret"]);
app.UseCookieAuthentication(new CookieAuthenticationOptions { CookieName = "AuthCookie" , AuthenticationType=DefaultAuthenticationTypes.ApplicationCookie });
//// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Passive,
AuthenticationType = "JWT",
AllowedAudiences = new[] { audienceid },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, audiencesecret)
}
});
}
In your MVC controller when you receive the token de-serialize it and generate a cookie from the acceSs token
AccessClaims claimsToken = new AccessClaims();
claimsToken = JsonConvert.DeserializeObject<AccessClaims>(response.Content);
claimsToken.Cookie = response.Cookies[0].Value;
Request.Headers.Add("Authorization", "bearer " + claimsToken.access_token);
var ctx = Request.GetOwinContext();
var authenticateResult = await ctx.Authentication.AuthenticateAsync("JWT");
ctx.Authentication.SignOut("JWT");
var applicationCookieIdentity = new ClaimsIdentity(authenticateResult.Identity.Claims, DefaultAuthenticationTypes.ApplicationCookie);
ctx.Authentication.SignIn(applicationCookieIdentity);
With this a cookie will be created and [Authorize] attribute in MVC Site and WebAPI will honor this cookie.