HttpContext.Current.User.Identity.Name Alternative for Non-Windows User? - c#

I deployed an application to Azure. Internal users with Windows accounts are logged in automatically when they navigate to the application. External users need to enter their username and password to log into the application. Their username is an email address with a domain that is not that same as the domain used by internal users.
I use HttpContext.Current.User.Identity.Name to set the CreatedBy and ModifiedBy values. I also use #User.Identity.Name in a view to display a greeting. Both of these do not display a value for external users with non-Windows accounts.
What are the alternative options for non-Windows accounts to get these values?
Startup.Auth.cs
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var clientId = ConfigurationManager.AppSettings["ida:ClientId"];
var aADInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
var tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
var postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
var authority = string.Format(CultureInfo.InvariantCulture, aADInstance, tenantId);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
CookieManager = new SystemWebChunkingCookieManager()
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.Upn,
RoleClaimType = ClaimTypes.Role
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/");
return Task.FromResult(0);
}
}
}
);
}
}
I tried seeing if HttpContext.Current.User.Identity.Name had other options to get the value needed, such as after Identity and after User. I also checked to see if the active directory user profile had any missing values, such as email address or name.

In ASP.NET Core, the current user's identity information can be accessed through the User property on the HttpContext class.
Whereas the HttpContext.Current property is not available in ASP.NET Core. Instead, you can use dependency injection to get an instance of the IHttpContextAccessor interface and use it to access the current HttpContext.
public class HomeController : Controller
{
private readonly IHttpContextAccessor _contextAccessor;
public HomeController(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public IActionResult Index()
{
var userName = _contextAccessor.HttpContext.User.Identity.Name;
if (string.IsNullOrEmpty(userName) && _contextAccessor.HttpContext.User.Identity.IsAuthenticated)
{
userName = _contextAccessor.HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value;
}
return View(userName);
}
}
In the Startup.cs file, configure the authentication in the ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = new PathString("/Account/Login");
options.AccessDeniedPath = new PathString("/Account/AccessDenied");
});
}
In startup.cs class, in the configure method, use the UseWindowsAuthentication and UseCookieAuthentication for internal and external users.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
if (context.User.Identity.IsAuthenticated && context.User.Identity.AuthenticationType == "NTLM")
{
var email = context.User.Identity.Name;
if (!email.EndsWith("#internal-domain.com"))
{
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
context.Response.Redirect("/Account/Login");
return;
}
}
await next();
});
app.UseWindowsAuthentication();
app.UseCookieAuthentication();
}
Create a Login action method that handles the external user login:
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
if (IsValidUser(model.Email, model.Password))
{
if (!model.Email.EndsWith("#internal-domain.com"))
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, model.Email));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid UserName.");
}
}
else
{
ModelState.AddModelError("", "Invalid password.");
}
}
return View(model);
}
private bool IsValidUser(string email, string password)
{
// check with DB to compare the credentials.
return true;
}
I use HttpContext.Current.User.Identity.Name to set the CreatedBy and ModifiedBy values.
I also use #User.Identity.Name in a view to display a greeting.
Both of these do not display a value for external users with non-Windows accounts.
HttpContext.Current.User.Identity.Name and #User.Identity.Name are used to retrieve the user's name in an ASP.NET application.
These properties are based on the authentication mechanism being used in the application.
If the application is using Windows authentication, the User.Identity.Name property will return the user's Windows login name.
If the application is using forms authentication, the User.Identity.Name property will return the username that the user entered when logging in.
In the view, you can use the following code to check if user is authenticated.
#if (User.Identity.IsAuthenticated)
{
<text>Welcome, #User.Identity.Name</text>
}
else
{
<text>Welcome, User</text>
}
Windows Login:
Reference :
Forms and Windows Authentication
Thanks # mvolo for the blog.

For this question, I updated NameClaimType = ClaimTypes.Upn to NameClaimType = ClaimTypes.Name.
I first chose Upn instead of Name because Upn seemed more "unique" per their descriptions.
I confirmed with an external user that the username is now displayed.

Related

How to use both Azure AD authentication and Identity on ASP.NET Core 3?

The web application should allow internal employees with AD accounts to authenticate in the app using Azure AD Authentication. External users should be able to register and sign in using ASP.NET Core Identity. I can implement each one separately but not together in the same app. When I add both authentications to the same app, the ASP.NET Core Identity works perfectly. I can register and log in using Identity with no problem. However when I try to log in with Azure AD, the app redirects me to my tenant's login page, I submit a username and password, it redirects me back to the application but no user is authenticated. I hit the login button again and the same thing happens. It seems that the web app or browser is not saving the access token or something like that.
What am I doing wrong? Is it even possible to have two sets of authentication on the same app?
Thanks. Here's the code:
Packages
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
Startup Class
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) => Configuration = configuration;
public void ConfigureServices(IServiceCollection services)
{
// Add Azure AD authentication
services.AddAuthentication(defaultScheme: AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
// Add the application db context
services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// Add Identity using Entity Framework Core
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
// Configure Identity
services.Configure<IdentityOptions>(options =>
{
// Password settings.
options.Password.RequireDigit = true;
options.Password.RequireLowercase = true;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequiredLength = 6;
options.Password.RequiredUniqueChars = 1;
// Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings.
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._#+";
options.User.RequireUniqueEmail = true;
});
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
User Controller
This is a custom controller where we handle HTTP requests related to authentication.
private readonly UserManager<ApplicationUser> userManager;
private readonly SignInManager<ApplicationUser> signInManager;
public UserController(UserManager<ApplicationUser> um, SignInManager<ApplicationUser> sm) =>
(userManager, signInManager) = (um, sm);
// Internal employee users will authenticate using Azure AD
[HttpGet("internal-signin")]
public ChallengeResult InternalSignIn(string returnUrl = "/") =>
Challenge(new AuthenticationProperties { RedirectUri = returnUrl }, AzureADDefaults.AuthenticationScheme);
// Display view with a form to create a new external user account
[HttpGet("register")]
public ViewResult Register() => View();
// Create a new account for an external user
[HttpPost("register")]
public async Task<IActionResult> Register(RegistrationInputModel inputModel)
{
// Check if the model state is valid
if (!ModelState.IsValid)
{
// Redirect to the Register view
return View(viewName: nameof(Register), model: inputModel);
}
// Create an application user object
ApplicationUser user = new ApplicationUser
{
// Map the fields of the input model with the user
UserName = inputModel.Email,
Email = inputModel.Email,
FirstName = inputModel.FirstName,
LastName = inputModel.LastName,
Company = inputModel.CompanyName,
};
// Try to register the user on the database
IdentityResult result = await userManager.CreateAsync(user, inputModel.Password);
// If failed, then set the error messages into the model state
if (!result.Succeeded)
{
foreach (IdentityError error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
// Return the user to the registration view
return View(viewName: nameof(Register), model: inputModel);
}
// Sign In the user
await signInManager.SignInAsync(user, isPersistent: false);
// Otherwise, redirect the user to the index page
return RedirectToAction(nameof(HomeController.Index), controllerName: "Home");
}
// External users sign out action
[HttpGet("signout")]
[Authorize]
public async Task<IActionResult> SignOut()
{
await signInManager.SignOutAsync();
return RedirectToAction(nameof(HomeController.Index), "Home");
}
// Display form to login for external users
[HttpGet("signin")]
public ViewResult SignIn() => View();
// Login an external user
[HttpPost("signin")]
public async Task<IActionResult> SingIn(SingInInputModel inputModel)
{
// Check if the model state is valid
if (!ModelState.IsValid)
{
// Send the user back to the sign in view
return View(viewName: nameof(SignIn), model: inputModel);
}
// Try to sign in the user
SignInResult result = await signInManager
.PasswordSignInAsync(inputModel.Email, inputModel.Password, inputModel.RememberMe, lockoutOnFailure: false);
// Check if the login was unsuccessful
if (!result.Succeeded)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(viewName: nameof(SignIn), model: inputModel);
}
// Send the user back to the index page
return RedirectToAction(nameof(HomeController.Index), "Home");
}
Application User
public class ApplicationUser : Microsoft.AspNetCore.Identity.IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
}
If using ASP.NET Core Identity with Azure AD login , you can set CookieSchemeName to Identity.External so that asp.net core identity can get the external user profile from external identity provider , and create a local user associated with external user :
In appsettings.json :
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "peterpad.onmicrosoft.com",
"TenantId": "cb1c3f2e-a2dd-4fde-bf8f-f75ab18b21ac",
"ClientId": "0c0ec562-a9bb-4722-b615-6dcbdc646326",
"CallbackPath": "/signin-oidc",
"CookieSchemeName": "Identity.External"
},
Then if you want to challenge Azure AD login in MVC controller , you should provide the scheme name , config redirect url after authentication to Identity/Account/ExternalLoginand Callbackhandler , in that handler asp.net core identity will let your enter username and create a local user :
[HttpGet("internal-signin")]
public ChallengeResult InternalSignIn(string returnUrl = "/")
{
var redirectUrl = Url.Page("/Account/ExternalLogin", pageHandler: "Callback", values: new { returnUrl , area = "Identity" });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(AzureADDefaults.AuthenticationScheme, redirectUrl);
return new ChallengeResult(AzureADDefaults.AuthenticationScheme, properties);
}

How to add additional claims to ClaimsPrincipal after ADFS authentication on MVC app

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>

How Owin Use OAuthAuthorizationServer?

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

How to prevent SignOutResult from resulting in a redirect loop?

I'm using a logoff method in my AccountController based off of the MusicStore example Microsoft provides:
public class AccountController : Controller
{
public async Task<IActionResult> Logout()
{
return new SignOutResult("OpenIdConnect", new AuthenticationProperties
{
RedirectUri = Url.Action("Index", "Home")
});
////_logger.LogInformation("{userName} logged out.", userName);
}
}
(We're using OpenID Connect for authentication.)
This method does not sign off the user; instead, it redirects back to itself in an infinite loop.
What's the proper way in .NET Core 1.0.0 to sign off the user when using OpenID Connect?
Update:
I tried using the SignOut method below, but ended up trapped in a 302 redirect loop to
/Account/SignOut?post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A10565%2FAccount%2FSignedOut
More info:
Our authentication setup in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddMvc(options =>
{
// Globally require users to be authenticated for all controller actions
options.Filters.Add(
new AuthorizeFilter(
new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build()));
});
...
public void Configure(IApplicationBuilder app,
ILoggerFactory loggerFactory,
IHostingEnvironment env)
{
...
app.UseCookieAuthentication(new CookieAuthenticationOptions());
OpenIdConnectOptions opts = new OpenIdConnectOptions()
{
ClientId = Configuration["Oidc:ClientId"],
ClientSecret = Configuration["Oidc:ClientSecret"],
Authority = Configuration["Oidc:BaseUrl"],
ResponseType = OpenIdConnectResponseType.Code,
AutomaticAuthenticate = true,
AutomaticChallenge = true
};
app.UseMiddleware<OktaOidcMiddleware>(Options.Create(opts));
The following is what I use for Azure Active Directory OIDC sign out
public IActionResult SignOut()
{
var callbackUrl = Url.Action("SignedOut", "Account", values: null, protocol: Request.Scheme);
return SignOut(new AuthenticationProperties { RedirectUri = callbackUrl },
CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme);
}
public async Task EndSession()
{
// If AAD sends a single sign-out message to the app, end the user's session, but don't redirect to AAD for sign out.
await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
public async Task<IActionResult> SignedOut()
{
if (HttpContext.User.Identity.IsAuthenticated)
{
await EndSession();
}
return View();
}

How to expose /Token End point from Startup.Auth.cs with Identity v2

I am working with ASP.NET Identity 2 and trying to enable Token Authentication. From the Identity 2 sample there is nothing about Token Authentication so I setup myself by looking at different post. I am following the last answer of this post app.UseOAuthBearerTokens with ASP.NET Identity 2.0's DbContext middleware?
and able to setup each and everything but now when I try to reach this end point on browser http://localhost:6722/token getting 404 error. Any idea?
Update:
Here is my ApplicationOAuthProvider.cs
public class ApplicationOAuthProvider<TUserManager, TUser, TKey> : OAuthAuthorizationServerProvider
where TUserManager : UserManager<TUser, TKey>
where TUser : class, IUser<TKey>
where TKey : IEquatable<TKey>
{
private readonly string _publicClientId;
public ApplicationOAuthProvider(string publicClientId)
{
if (publicClientId == null)
{
throw new ArgumentNullException("publicClientId");
}
_publicClientId = publicClientId;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.Get<TUserManager>(_publicClientId);
TUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await userManager.CreateIdentityAsync(user,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = await userManager.CreateIdentityAsync(user,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
{
context.AdditionalResponseParameters.Add(property.Key, property.Value);
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// Resource owner password credentials does not provide a client ID.
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == _publicClientId)
{
Uri expectedRootUri = new Uri(context.Request.Uri, "/");
if (expectedRootUri.AbsoluteUri == context.RedirectUri)
{
context.Validated();
}
}
return Task.FromResult<object>(null);
}
public static AuthenticationProperties CreateProperties(string userName)
{
IDictionary<string, string> data = new Dictionary<string, string>
{
{
"userName", userName
}
};
return new AuthenticationProperties(data);
}
}
Here is my Startup.Oauth.cs
public partial class Startup
{
static Startup()
{
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider<ApplicationUserManager, User, int>(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = false
};
}
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDb.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// 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, User, int>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
getUserIdCallback: (claim) => int.Parse(claim.GetUserId()))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
// 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);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication();
}
}
And I am trying to access /Token end point directly from the browser and it throws 404 error.
I had a similar issue today, what fixed the problem for me was installing the following Nuget package.
I have no idea why it wasn't installed with all of the other packages, but give it a shot and let us know.
The package name is Microsoft.Owin.Host.SystemWeb
Do you have the other part of Startup class? Because you should have a Startup.cs file in your web project that is calling your ConfigureAuth method. If not you will get a 404 exception. The startup.cs file should look like this:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(YOUR_NAME_SPACE_TO_THE_STARTUP_FILE.Startup))]
namespace YOUR_NAME_SPACE_TO_THE_STARTUP_FILE
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
If you then trying to access the page through your browser you should get this error:
{
error: "unsupported_grant_type"
}
In my case I wrapped the AllowInsecureHttp in an #if DEBUG processor directive, and ended up publishing it to the server (as Release) and my customer didn't afford SSL.
After removing the DEBUG condition it all works fine now.
I've just had a similar (if not same) issue where I was getting 404s when accessing /token. Eventually worked out that it was due to the order I was calling things in the Startup.Configuration method. I was calling ConfigureAuth(app) at the very bottom of this method, after I had added Ninject config (ie. app.UseNinjectMiddleware(CreateKernel).UseNinjectWebApi(config);. Moving the ConfigureAuth above the Ninject setup fixed this issue and /token now works.

Categories