Current user in owin authentication
On method GrantResourceOwnerCredentials once you add claims after validating the username password you need to add this claim:
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
By doing this the UserId will be filled when you call User.Identity.Name inside protected controller. Hope this solves your issue.
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on September 26, 2020Comments
-
Admin almost 4 years
I started to build a web api for mobile apps and I'm having a hard time with implementing authentication. I use Bearer and although everything is supposed to be fine, I cannot get the current user from action in controller. HttpContext.Current.User.Identity.Name is null (the same is result of HttpContext.Current.User.Identity.GetUserId()). Here are the pieces of important code:
Startup.cs:
public partial class Startup { public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); ConfigureAuth(app); WebApiConfig.Register(config); app.UseWebApi(config); } }
Startup.Auth.cs
public partial class Startup { static Startup() { OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/token"), Provider = new ApplicationOAuthProvider(), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), AllowInsecureHttp = true }; OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); } public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } public static string PublicClientId { get; private set; } public void ConfigureAuth(IAppBuilder app) { app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions { AccessTokenProvider = new AuthenticationTokenProvider() }); app.UseOAuthBearerTokens(OAuthOptions); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); } }
ApplicationOAuthProvider.cs:
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { string clientId, clientSecret; if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) { return SetErrorAndReturn(context, "client error", ""); } if (clientId == "secret" && clientSecret == "secret") { context.Validated(); return Task.FromResult<object>(null); } return SetErrorAndReturn(context, "client error", ""); } public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); using (AuthRepository _repo = new AuthRepository()) { IdentityUser user = await _repo.FindUser(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The user name or password is incorrect."); return; } } var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim("sub", context.UserName)); identity.AddClaim(new Claim("role", "user")); context.Validated(identity); } 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); }
AuthRepository.cs:
public class AuthRepository : IDisposable { private readonly AuthContext _ctx; private readonly UserManager<IdentityUser> _userManager; public AuthRepository() { _ctx = new AuthContext(); _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx)); } public async Task<IdentityResult> RegisterUser(UserModel userModel) { var user = new IdentityUser { UserName = userModel.UserName }; var result = await _userManager.CreateAsync(user, userModel.Password); return result; } public async Task<IdentityUser> FindUser(string userName, string password) { IdentityUser user = await _userManager.FindAsync(userName, password); return user; } public void Dispose() { _ctx.Dispose(); _userManager.Dispose(); } }
AuthContext.cs:
public class AuthContext : IdentityDbContext<IdentityUser> { public AuthContext() : base("AuthContext") { } }
And finnaly ValuesController.cs:
[Authorize] public class ValuesController : ApiController { public IEnumerable<string> Get() { return new String[] {HttpContext.Current.User.Identity.Name, HttpContext.Current.User.Identity.GetUserId(),ClaimsPrincipal.Current.Identity.Name}; } }
When i go to this action, i get null 3 times. Despite that, the whole authentication proccess seems to be fine - only when i send a good token, i have access. Does anybody have an idea what is wrong here?