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.
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 trying to undesratnd owin and OAuthAuthorizationServer.
I know that Outh2 has 4 parts:
1- Resource Owner
2- Resource Server:
3- Client Applications:
4- Authorization Server:
I have implemnted owin and Authorization Server in a simple application.
The application is working fine.
I just want to learn more regading the Outh stuffs.
so I have in my srartp class :
public class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);//this is very important line cross orgin source(CORS)it is used to enable cross-site HTTP requests //For security reasons, browsers restrict cross-origin HTTP requests
var OAuthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),//token expiration time
Provider = new OauthProvider()
};
app.UseOAuthBearerTokens(OAuthOptions);
app.UseOAuthAuthorizationServer(OAuthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);//register the request
}
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
Then I created my OauthProvider
here is my class
public class OauthProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
//First request will come here, this method will validate the request wheather it has crendtials(UserName and Password) if the request not contain username and
//password the request will reject from here not proceded any further
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
//If the request has valid and it contain username and password than this method will check correct crenstials and than generate a valid token
var identity = new ClaimsIdentity(context.Options.AuthenticationType); //it will check the authenticate type
using (var db = new DataContext())
{
if (db != null)
{
var user = db.Users.Where(o => o.UserName == context.UserName && o.Password == context.Password).FirstOrDefault();
if (user != null)
{
//Store information againest the request
identity.AddClaim(new Claim("UserName", context.UserName));
identity.AddClaim(new Claim("LoggedOn", DateTime.Now.ToString()));
context.Validated(identity);
}
else
{
context.SetError("Wrong Crendtials", "Provided username and password is incorrect");
context.Rejected();
}
}
else
{
context.SetError("Wrong Crendtials", "Provided username and password is incorrect");
context.Rejected();
}
return;
}
}
}
So if I want to undersatnd the OAuth parts.
How can I define what I have done to each part ?
Notice That this is a web api project ?
Any useful informatuin is helpful.
Thanks
Lets say I have a hub:
public class MyHub: Hub<IMyHub> {
public MyHub(){}
public Task DoWork(){
var principal = this.Context.User; // Currently WindowsIdentity as its not authenticated
var auth = new OwinContext(this.Context.Request.Environment).Authentication;
var types = auth.GetAuthenticationTypes(); // Empty list
// ....
}
}
If I execute same code inside an WebApi2 Controller the .GetAuthenticationTypes() would give me the correct result of pre'configured authProviders.
Any ideas why its not behaving like within an controller? Is that by design?
Update 1
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
var httpConfig = new HttpConfiguration();
// .. Ioc Registering Hubs
WebApiConfig.Register(httpConfig);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
// Have also tried registering signalr here before auth
// app.MapSignalR("/signalR", new HubConfiguration() { .... });
app.UseOAuthIntrospection(options =>
{
//...
options.AuthenticationType = OAuthDefaults.AuthenticationType;
options.ClientId = clientId;
options.ClientSecret = clientSecret;
options.RequireHttpsMetadata = false;
options.AuthenticationMode = AuthenticationMode.Passive;
options.Events = new OAuthIntrospectionEvents()
{
OnRetrieveToken = context =>
{
// Getting token from QueryString passed from js app.
var token = context.Request.Query["Authorization"];
if (!string.IsNullOrWhiteSpace(token))
{
context.Token = token;
}
return Task.CompletedTask;
}
}
//...
};
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR("/signalR", new HubConfiguration() { .... });
app.UseWebApi(httpConfig); // Have tried swapping these 0 effect
}
In your Owin startup part, you should configure app.MapSignalR(); before registering authentication.
public void Configuration(IAppBuilder app)
{
app.MapSignalR();//Configure it first
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Home/Index")
});
}
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?
I try to use owin authentication manager to authenticate users but User.Identity.IsAuthenticated is still false.
Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
Startup.Auth.cs
public partial class Startup
{
public static Func<UserManager<ApplicationUser>> UserManagerFactory { get; set; }
public Startup()
{
UserManagerFactory = () =>
{
var userManager = new UserManager<ApplicationUser>(new CustomUserStore());
return userManager;
};
}
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
LogoutPath = new PathString("/Account/LogOff"),
ExpireTimeSpan = TimeSpan.FromDays(7)
});
}
}
Some part of authentication action:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
var authManager = return HttpContext.GetOwinContext().Authentication;
authManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
var identity = await userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
authManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, identity);
}
The identity creates successfully but SignIn method doesn't sign in a user. What's wrong?
It's a very stupid mistake. I have forgotten to call ConfigureAuth method.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app); // <-- this
app.MapSignalR();
}
}