web-dev-qa-db-fra.com

Renvoie plus d'informations au client en utilisant OAuth Génération de jetons de support et Owin dans WebApi

J'ai créé une application WebApi et une application Cordova. J'utilise des requêtes HTTP pour communiquer entre l'application Cordova et WebAPI. Dans WebAPI, j'ai implémenté OAuth génération de jetons de support).

public void ConfigureOAuth(IAppBuilder app)
    {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider(new UserService(new Repository<User>(new RabbitApiObjectContext()), new EncryptionService()))
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }

et cela se trouve à l'intérieur de l'implémentation SimpleAuthorizationServerProvider

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
       context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        // A little hack. context.UserName contains the email
        var user = await _userService.GetUserByEmailAndPassword(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "Wrong email or password.");
            return;
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);
    }

après une demande de connexion réussie à l'API depuis l'application Cordova, je reçois le fichier JSON suivant.

{"access_token":"some token","token_type":"bearer","expires_in":86399}

Le problème est que j'ai besoin de plus d'informations sur l'utilisateur. Par exemple, j'ai un champ UserGuid dans la base de données et je souhaite l'envoyer à l'application Cordova une fois la connexion établie avec succès et l'utiliser ultérieurement dans d'autres demandes. Puis-je inclure d'autres informations à renvoyer au client, autres que "access_token", "token_type" Et "expires_in"? Si non, comment puis-je obtenir l'utilisateur dans l'API basé sur access_token?


EDIT:

Je pense que j'ai trouvé une solution de contournement. J'ai ajouté le code suivant à l'intérieur de GrantResourceOwnerCredentials

identity.AddClaim(new Claim(ClaimTypes.Name, user.UserGuid.ToString()));

et après cela, j'accède au GUID à l'intérieur de mon contrôleur comme ceci: User.Identity.Name

Je peux aussi ajouter le guid avec un nom personnalisé identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

Je suis toujours intéressé de savoir s’il existe un moyen de renvoyer davantage de données au client avec le jeton porteur JSON.

61
Ivan Stoyanov

Vous pouvez ajouter autant de revendications que vous le souhaitez.
Vous pouvez ajouter le jeu standard de revendications de System.Security.Claims ou créez le vôtre.
Les revendications seront cryptées dans votre jeton, elles ne seront accessibles qu'à partir du serveur de ressources.

Si vous voulez que votre client puisse lire les propriétés étendues de votre jeton, vous avez une autre option: AuthenticationProperties.

Supposons que vous souhaitiez ajouter quelque chose afin que votre client puisse y avoir accès. C'est la voie à suivre:

var props = new AuthenticationProperties(new Dictionary<string, string>
{
    { 
        "surname", "Smith"
    },
    { 
        "age", "20"
    },
    { 
    "gender", "Male"
    }
});

Vous pouvez maintenant créer un ticket avec les propriétés que vous avez ajoutées ci-dessus:

var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);

C'est le résultat que votre client va chercher:

.expires: "Tue, 14 Oct 2014 20:42:52 GMT"
.issued: "Tue, 14 Oct 2014 20:12:52 GMT"
access_token: "blahblahblah"
expires_in: 1799
age: "20"
gender: "Male"
surname: "Smith"
token_type: "bearer"

D'autre part, si vous ajoutez des revendications, vous pourrez les lire sur votre serveur de ressources dans votre contrôleur d'API:

public IHttpActionResult Get()
{
    ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

    return Ok();
}

Votre ClaimsPrincipal contiendra votre nouvelle réclamation guid que vous avez ajoutée ici:

identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));

Si vous voulez en savoir plus sur owin, les jetons porteurs et l'API Web, voici un très bon tutoriel ici et ceci article vous aidera à comprendre tous les concepts sous-jacents Serveur d'autorisation et Serveur de ressources .

[~ # ~] met à jour [~ # ~] :

Vous pouvez trouver un exemple de travail ici . Ceci est un Web Api + Owin auto-hébergé.
Il n'y a pas de base de données impliquée ici. Le client est une application de la console (il existe également un exemple html + JavaScript) qui appelle une authentification Web transmettant des informations d'identification.

Comme l'a suggéré Taiseer, vous devez remplacer TokenEndpoint:

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);
}

Activez 'Plusieurs projets de démarrage' dans Solution -> Propriétés et vous pourrez l'exécuter immédiatement.

90
LeftyX

Ma recommandation est de ne pas ajouter de revendications supplémentaires au jeton si ce n'est pas nécessaire, car cela augmentera la taille du jeton et vous continuerez à l'envoyer à chaque demande. Comme LeftyX le conseille, ajoutez-les en tant que propriétés, mais veillez à surcharger la méthode TokenEndPoint pour obtenir ces propriétés en tant que réponse lorsque vous obtenez le jeton avec succès. Sans ce point de terminaison, les propriétés ne seront pas renvoyées dans la réponse.

 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);
    }

Vous pouvez vérifier mon repo ici pour un exemple complet. J'espère que ça va aider.

43
Taiseer Joudeh