EDIT 10/24 Je pense que tout cela était une erreur d'utilisateur probable - voir ma réponse ci-dessous pour remédier avant d'obtenir trop profondément dans cette questionEn utilisant un client AutoRest C# pour accéder à une API Web avec un jeton porteur - TokenCredentials ne fonctionne pas
TL; DR: Pour mon OAuth 2.0 flux de code ...
Pourquoi mon
TokenCredentials
fonctionne pas avec mon client AutoRest? Je reçois aucun jeton porteur appliqué à la demande/sans en-tête d'autorisation définie
Je sais que mon pipeline fonctionne déjà ..
En utilisant le code de this azure sample, ce qui est un client AutoRest, je peut obtenir avec succès mon access_token
et peut obtenir JSON de mon projet Web API protégé .. donc j'ai exclue tous les trucs .. condition sine qua non, je sais que mon pipelinière
configuration mon AutoRest ..
1.) Téléchargé de GitHub this AutoRest repo v1.1.0
2.) Téléchargé mon fanfaronnades JSON sur le disque, enregistré en tant que swagger.json
3.) cette commande-Ran en ligne pour générer des fichiers C#:
autorest --input-file=swagger.json --csharp --output-folder=MyCorp_ApiClient_Tsl --namespace='MyCorp.ApiClient' --add-credentials
4.) classes générées Copié dans mon .NET 4.6.2 site web
5.) Ce sont mes nugets:
- Microsoft.Rest.ClientRuntime version="2.3.8"
- Microsoft.Rest.ClientRuntime.Azure.Authentication version="2.3.1"
- Microsoft.IdentityModel.Clients.ActiveDirectory version="2.28.3"
Voici ce qui ne fonctionne pas:
AdalTokenHelper tokenHelper = new AdalTokenHelper();//helper code further below
string token = await tokenHelper.GetTokenString();
var svcClientCreds = new TokenCredentials(token, "Bearer");
client = new MyCorp.ApiClient(new Uri(apiRsrcUrl), svcClientCreds,
new DelegatingHandler[] { new MyAzureTracingHandler() });
//make call to OData controller...
MyCorp.ApiClient.Models.ODataResponseListStatus statusList = await client.Status.GetStatusAsync(expand: "StatusType",cancellationToken: defaultCancelThreadToken);
return View(statusList.Value);
J'ai variations essayé de ce qui précède, en utilisant différentes années ctor de TokenCredentials
, mais peu importe, je peux mettre mon point d'arrêt dans MyAzureTracingHandler
et voir le demande n'a pas en-têtes d'autorisation appliquée .. donc j'obtenir la réponse 401 Unauthorized
attendue.
Si je modifie MyAzureTracingHandler
pour accepter mon instance de TokenCredentials
, je peux forcer la requête à appliquer le jeton support approprié.
Cela fonctionne, mais se sent hack-ish:
J'ai changé mon original extrait de l'instanciation client de ceci:
client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds,
new DelegatingHandler[] { new MyAzureTracingHandler() });
à ceci:
client = new ApiClient(new Uri(apiRsrcUrl), svcClientCreds,
new DelegatingHandler[] { new MyAzureTracingHandler(svcClientCreds) });
Et à l'intérieur du SendAsync
méthode de MyAzureTracingHander
Je fais ceci:
await svcClientCreds.ProcessHttpRequestAsync(request, cancellationToken);
Est-ce que je fais quelque chose de mal? Je ne pense pas que je devrais avoir à passer le ServiceClientCredentials
dans deux fois en instanciant mon client.
Annexe A - Obtenir le jeton d'accès via ADAL:
private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
private string tslResourceID = ConfigurationManager.AppSettings["ross:TslWebApiResourceId"];
private static string loginRedirectUri = ConfigurationManager.AppSettings["ross:LoginRedirectUri"];
private AuthenticationContext authContext;
private AuthenticationResult authenticationResult;
public async Task<string> GetTokenString()
{
string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
try
{
// get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
ClientCredential clientcred = new ClientCredential(clientId, appKey);
// initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
authContext = new AuthenticationContext(Startup.Authority, new ADALTokenCache(userObjectID));
UserIdentifier userIdentifier = new UserIdentifier(userObjectID, UserIdentifierType.UniqueId);
authenticationResult = await authContext.AcquireTokenSilentAsync(tslResourceID, clientcred, userIdentifier);
}
catch(AdalException ex)
{
throw ex;
}
return authenticationResult.AccessToken;
}