API Web ASP.NET et OpenID Connect: comment obtenir un jeton d’access à partir d’un code d’autorisation

J’essaie de faire fonctionner OpenID Connect … Un utilisateur de mon API Web a réussi à obtenir un code d’autorisation d’un fournisseur OpenID Connect. Comment suis-je censé transmettre ce code à mon API Web ASP.NET? Comment dois-je configurer OWIN Middleware pour pouvoir obtenir un jeton d’access à l’aide du code d’autorisation?

MISE À JOUR: Un SPA utilise AJAX pour communiquer avec mon service Web (API Web ASP.NET). Dans mon service Web, utilisez le middleware OWIN. J’ai défini OpenIDConnect comme mécanisme d’authentification. Lorsque le service Web est appelé pour la première fois, il a correctement redirigé l’utilisateur vers la page de connexion du fournisseur OpenID Connect. L’utilisateur pouvait se connecter et obtenir un code d’autorisation à la suite. Autant que je sache, ce code peut maintenant être utilisé (par mon service Web) pour un jeton d’access. Cependant, je ne sais pas comment renvoyer ce code sur mon service Web (cette opération est-elle effectuée à l’aide d’un en-tête?), Puis quoi configurer pour obtenir le jeton d’access. Je suppose que je pourrais appeler le sharepoint terminaison du jeton manuellement, mais j’aimerais plutôt tirer parti du composant OWIN.

L’approche recommandée consiste à utiliser l’événement AuthorizationCodeReceived pour échanger le code d’authentification contre un jeton d’access. Vittorio a une entrée de blog qui décrit le stream global.

Voici un exemple de cet exemple d’application sur GitHub du code Startup.Auth.cs pour configurer ceci:

 app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = Authority, Notifications = new OpenIdConnectAuthenticationNotifications() { AuthorizationCodeReceived = (context) => { var code = context.Code; ClientCredential credential = new ClientCredential(clientId, appKey); ssortingng tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; ssortingng signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value; AuthenticationContext authContext = new AuthenticationContext(ssortingng.Format("https://login.windows.net/{0}", tenantID), new EFADALTokenCache(signedInUserID)); AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode( code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceID); return Task.FromResult(0); }, ... } 

Remarque: l’ événement AuthorizationCodeReceived est appelé une seule fois lorsque l’autorisation a réellement lieu. Si le code d’autorisation est déjà généré et stocké, cet événement n’est pas appelé. Vous devez vous déconnecter ou supprimer les cookies pour que cet événement se produise.

BenV a déjà répondu à la question, mais il y a plus à considérer.

 class partial Startup { public void ConfigureAuth(IAppBuilder app) { // ... app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = clientId, Authority = authority, Notifications = new OpenIdConnectAuthenticationNotifications() { AuthorizationCodeReceived = (context) => { ssortingng authorizationCode = context.Code; // (sortingcky) the authorizationCode is available here to use, but... return Task.FromResult(0); } } } } } 

Deux problèmes:

  • Tout d’abord, authorizationCode va expirer rapidement. Il n’y a aucun sens à le stocker.
  • Le deuxième problème est que l’événement AuthorizationCodeReceived ne sera pas déclenché pour les rechargements de page tant que authorisationCode n’est pas expirée et n’est pas stockée dans la session.

Ce que vous devez faire, c’est appeler AcquireTokenByAuthorizationCodeAsync qui le mettra en cache et gérera correctement à l’intérieur de TokenCache.DefaultShare :

 AuthorizationCodeReceived = (context) => { ssortingng authorizationCode = context.Code; AuthenticationResult tokenResult = await context.AcquireTokenByAuthorizationCodeAsync(authorizationCode, new Uri(redirectUri), credential); return Task.FromResult(0); } 

Désormais, avant chaque appel à la ressource, AcquireTokenSilentAsync pour obtenir AcquireTokenSilentAsync (il utilisera TokenCache ou utilisera silencieusement refreshToken). Si le jeton a expiré, il AdalSilentTokenAcquisitionException exception AdalSilentTokenAcquisitionException (procédure d’ AdalSilentTokenAcquisitionException renouvellement du code d’access).

 // currentUser for ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier") AuthenticationResult authResult = await context.AcquireTokenSilentAsync(resourceUri, credential, currentUser); 

L’appel AcquireTokenSilentAsync est très rapide si le jeton est mis en cache.

Vous devez contourner la validation owin par défaut pour créer une autorisation personnalisée:

  new OpenIdConnectAuthenticationOptions { ..., TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters { ValidateIssuer = false },