I'm creating an application using OWIN without using ASP Identity. I've struggled to find any documentation on this as 99% of material out there is using Identity with OWIN.
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
//
// Wires up WebApi to Owin pipeline
//
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieDomain = ".devdomain.com",
CookieName = "AuthCookie",
});
}
}
API Controller
public void Login(string id)
{
var authentication = System.Web.HttpContext.Current.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("Application");
identity.AddClaim(new Claim(ClaimTypes.Name, "<user name>"));
identity.AddClaim(new Claim("CompanyId", id));
authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity, new AuthenticationProperties()
{
IsPersistent = true
});
}
When I invoke the Login method it creates a new identity signs the user in. However a cookie isn't returned in the response.
Am I missing something?
Related
We have an MVC 5 web app that uses ADFS 4 authentication. I'm trying to find the best place where I can add additional claims into the ClaimsPrincipal, after authentication has been completed.
Are there any events I can access, like OnAuthenticated? How do I access this kind of event?
This is what I intend to use once I can access the event:
IOwinContext context = Request.GetOwinContext();
if (appRoles != null)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity(System.Web.HttpContext.Current.User.Identity);
foreach (var role in appRoles)
{
claimsIdentity.AddClaim(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", role));
}
context.Authentication.AuthenticationResponseGrant = new AuthenticationResponseGrant
(new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties { IsPersistent = true });
}
EDIT:
This is what my App_Data\Startup.Auth.cs file looks like:
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
{
CookieManager = new SystemWebCookieManager()
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
}
}
I encountered similar problem and managed to find a way to add additional claims after ADFS login in my MVC 5 app. More info can be found on msdn link.
Here is code from that link.
Firstly create the new ClaimsAuthenticationManager class and inside set additional claims:
class SimpleClaimsAuthenticatonManager : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
}
return incomingPrincipal;
}
}
Afterwards specify this class in web.config file, under identityConfiguration element:
<system.identityModel>
<identityConfiguration>
<claimsAuthenticationManager type="ENTER YOUR NAMESPACE HERE.SimpleClaimsAuthenticatonManager, ENTER PROJECT NAME HERE" />
...
</identityConfiguration>
</system.identityModel>
I am new to WEB API ,here I need to implement a token based authentication for a login page .
As of now I have completed the token generate functions by providing static values for learning purpose .
Now What I want to do is I want to validate each request with the table which I have created in my SQL SERVER (LOGIN_TABLE) and generate Token instead of validate with Identity tables in web API.
Columns of LOGIN_TABLE
FirstName,LastName,UserName,Email,Password,CreationDate
I don't know is it possible or not ,if possible please help me to do that .
I have created my project as Web API template without MVC and choosed No Authentication then I have added all the necessary packages and classes.
Here I have added the code I have used to generate token based on the static values.
My_Controller.cs
[Authorize]
[HttpGet]
[Route("api/data/authenticate")]
public IHttpActionResult GetForAuthenticate()
{
var identity = (ClaimsIdentity)User.Identity;
return Ok("Hello" + identity.Name);
}
MyAutorizationServerProvider.cs
public class MyAuthorizationServerProvider :OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
if (context.UserName == "user" && context.Password == "123")
{
identity.AddClaim(new Claim(ClaimTypes.Role, "USER"));
identity.AddClaim(new Claim("username", "user"));
identity.AddClaim(new Claim(ClaimTypes.Name, "Sakthi"));
context.Validated(identity);
}else
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
//This enable cors orgin requests
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
var myProvider = new MyAuthorizationServerProvider();
OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(30),
Provider = myProvider
};
app.UseOAuthAuthorizationServer(options);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
}
}
AuthorizeAttribute.cs
public class AuthorizeAttribute :System.Web.Http.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actioncontext)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(actioncontext);
}else
{
actioncontext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
}
}
}
I am new to web API if I did any mistakes here please guide me to correct it .
Thanks .
I'm new to OWIN and ADFS. I'm trying to authenticate users from ADFS using OWIN middleware. But when i run the app and perform login, the return HttpContext.Current.GetOwinContext() is not initialized properly.
owin_middleware_startup.cs
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
ConfigureAuth(app);
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, // application cookie which is generic for all the authentication types.
LoginPath = new PathString("/login.aspx"), // redirect if not authenticated.
AuthenticationMode = AuthenticationMode.Passive
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
MetadataAddress = "https://adfs-server/federationmetadata/2007-06/federationmetadata.xml", //adfs meta data.
Wtrealm = "https://localhost/", //reltying party
Wreply = "/home.aspx" // redirect
});
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);
}
login.aspx.cs
private IAuthenticationManager AuthenticationManager
{
get { return HttpContext.Current.GetOwinContext().Authentication; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void loginSSObtn_Click(object sender, EventArgs e)
{
IdentitySignin("administrator");
}
private void IdentitySignin(string userName)
{
//Create list of claims for Identity
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, userName));
var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties()
{
AllowRefresh = true,
IsPersistent = true,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddDays(2)
}, identity);
//Response.Redirect("/home.aspx");
}
My goal is to redirect to the ADFS login and authenticate the user. Highly appreciate any help. Thanks.
Found the issue, I had missed the RUN method - app.Run() in the middle-ware. This inserts the extension to the OWIN startup. And executes it for all the requests.
Fix :
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
ConfigureAuth(app);
}
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);
app.UseCookieAuthentication(
new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, // application cookie which is generic for all the authentication types.
LoginPath = new PathString("/login.aspx"), // redirect if not authenticated.
AuthenticationMode = AuthenticationMode.Passive
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
AuthenticationType = "test auth",
MetadataAddress = "https://adfs-server/federationmetadata/2007-06/federationmetadata.xml", //adfs meta data.
Wtrealm = "https://localhost/", //reltying party
Wreply = "/home.aspx"//redirect
});
AuthenticateAllRequests(app, "test auth");
}
private static void AuthenticateAllRequests(IAppBuilder app, params string[] authenticationTypes)
{
app.Use((context, continuation) =>
{
if (context.Authentication.User != null &&
context.Authentication.User.Identity != null &&
context.Authentication.User.Identity.IsAuthenticated)
{
return continuation();
}
else
{
context.Authentication.Challenge(authenticationTypes);
return Task.Delay(0);
}
});
}
But if we want to execute the extensions/middle-wares only for some specific path then we can use app.Use() this is just one usage of it.
feel free to correct me if i'm wrong.
I have a Web API project that use UseJwtBearerAuthentication to my identity server.
Config method in startup looks like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseJwtBearerAuthentication(options =>
{
options.AutomaticAuthentication = true;
options.Authority = "http://localhost:54540/";
options.Audience = "http://localhost:54540/";
});
// Configure the HTTP request pipeline.
app.UseStaticFiles();
// Add MVC to the request pipeline.
app.UseMvc();
}
This is working, and I want to do the same thing in an MVC5 project. I tried to do something like this:
Web api:
public class SecuredController : ApiController
{
[HttpGet]
[Authorize]
public IEnumerable<Tuple<string, string>> Get()
{
var claimsList = new List<Tuple<string, string>>();
var identity = (ClaimsIdentity)User.Identity;
foreach (var claim in identity.Claims)
{
claimsList.Add(new Tuple<string, string>(claim.Type, claim.Value));
}
claimsList.Add(new Tuple<string, string>("aaa", "bbb"));
return claimsList;
}
}
I can't call web api if is set attribute [authorized] (If I remove this than it is working)
I created Startup. This code is never called and I don't know what to change to make it work.
[assembly: OwinStartup(typeof(ProAuth.Mvc5WebApi.Startup))]
namespace ProAuth.Mvc5WebApi
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
Uri uri= new Uri("http://localhost:54540/");
PathString path= PathString.FromUriComponent(uri);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = path,
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
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[] { "*" });
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
}
goal is to return claims from web api to client app. using Bearer Authentication.
Thanks for help.
TL;DR: you can't.
Authority refers to an OpenID Connect feature that has been added to the bearer middleware in ASP.NET 5: there's no such thing in the OWIN/Katana version.
Note: there's an app.UseJwtBearerAuthentication extension for Katana, but unlike its ASP.NET 5 equivalent, it doesn't use any OpenID Connect feature and must be configured manually: you'll have to provide the issuer name and the certificate used to verify tokens' signatures: https://github.com/jchannon/katanaproject/blob/master/src/Microsoft.Owin.Security.Jwt/JwtBearerAuthenticationExtensions.cs
You can get claims as:
IAuthenticationManager AuthenticationManager
{
get
{
return Request.GetOwinContext().Authentication;
}
}
public IHttpActionResult UserRoles()
{
return ok(AuthenticationManager.User.Claims.ToList());
}
This code should be in [Authorize] controller.
I have looked at ASP.NET Identity and it looks really complex and difficult to follow. Basically what I want to know is the easiest way to authorize a user on login so the [Authorize] data annotation will allow them through.
Follow these steps:
Install the following NuGet packages
Microsoft.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.Security
Microsoft.Owin.Security.Cookies
Inside App_Start folder, add a AuthConfig that look like this:
public static class AuthConfig
{
public const string DefaultAuthType = "DefaultAppCookie"; //example
public const string LoginPath = "System/SignIn"; //example
public static void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthType,
LoginPath = new PathString(LoginPath)
});
}
}
In the root path of the project, add a Startup.cs that look like this
[assembly: OwinStartup(typeof(YourPorject.Startup))]
namespace YourPorject
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
AuthConfig.ConfigureAuth(app);
}
}
}
To authenticate an user (usually inside a Login Action):
//user = the user that is loggin on, retrieved from database
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Name),
new Claim(ClaimTypes.Email, user.Email),
//some other claims
};
ClaimsIdentity identity = new ClaimsIdentity(claims, AuthConfig.DefaultAuthType);
IAuthenticationManager authManager = Request.GetOwinContext().Authentication;
authManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
You need to add a ClaimTypes.Role to authorize specific roles.