web-dev-qa-db-fra.com

Utilisateur actuel dans l'authentification Owin

J'ai commencé à créer une API Web pour les applications mobiles et j'ai du mal à implémenter l'authentification. J'utilise Bearer et bien que tout soit censé aller bien, je ne peux pas obtenir l'utilisateur actuel de l'action dans le contrôleur. HttpContext.Current.User.Identity.Name est null (le même résultat de HttpContext.Current.User.Identity.GetUserId ()). Voici les morceaux de code importants:

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")
        {

        }
    }

Et enfin 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};
    }
}

Lorsque je passe à cette action, j'obtiens null 3 fois. Malgré cela, l'ensemble du processus d'authentification semble bien - seulement lorsque j'envoie un bon jeton, j'ai accès. Quelqu'un at-il une idée de ce qui ne va pas ici?

32
user3558203

Sur la méthode GrantResourceOwnerCredentials une fois que vous ajoutez des revendications après avoir validé le mot de passe du nom d'utilisateur, vous devez ajouter cette revendication:

identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));

Ce faisant, le UserId sera rempli lorsque vous appelez User.Identity.Name à l'intérieur du contrôleur protégé. J'espère que cela résout votre problème.

67
Taiseer Joudeh