Nel precedente script abbiamo iniziato a esplorare il supporto al protocollo OAuth fornito da ASP.NET Web API grazie a un apposito middleware OWIN. In particolare ci siamo occupati di un sistema di autenticazione basato su username e password, che è idoneo nel contesto in cui un utente debba fornire le proprie credenziali, magari da un app per un device o una single page web application.
Oggi invece ci occuperemo del caso in cui sia un'applicazione a doversi autenticare presso il nostro servizio ASP.NET Web API. In questo caso, il modo più corretto è sfruttare un grant type di tipo client_credentials, con una richiesta simile alla seguente:
POST /token HTTP/1.1 Host: localhost:15986 Content-Type: application/x-www-form-urlencoded Cache-Control: no-cache grant_type=client_credentials&client_id=testclient&client_secret=testsecret
Come possiamo notare, questa richiesta include esclusivamente i campi client_id e client_secret, che possiamo immaginare come le vere e proprie credenziali dell'app che vogliamo autenticare. La validazione delle credenziali in Web API avviene ancora una volta grazie all'OAuthAuthorizationServerProvider che abbiamo configurato in Startup.Auth.cs:
public void ConfigureAuth(IAppBuilder app) { // .. altro codice qui .. OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId), .... }; // .. altro codice qui .. }
In pratica, ciò che dobbiamo fare è effettuare l'override di due metodi nella classe OAuthAuthorizationServerOptions per definire le modalità con cui:
- valideremo le credenziali dell'applicazione, nel metodo ValidateClientAuthentication;
- assegneremo i claims al principal, quando lo step precedente ha successo, tramite GrantClientCredentials.
Il codice da scrivere è piuttosto semplice:
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider { // .. altro codice qui .. public override Task ValidateClientAuthentication( OAuthValidateClientAuthenticationContext context) { string clientId, clientSecret; if (context.TryGetFormCredentials(out clientId, out clientSecret) && clientId == "testclient" && clientSecret == "testsecret") { context.Validated(); } return Task.FromResult<object>(null); } public override Task GrantClientCredentials( OAuthGrantClientCredentialsContext context) { ClaimsIdentity oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType); oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.ClientId)); var properties = new AuthenticationProperties(); var ticket = new AuthenticationTicket(oAuthIdentity, properties); context.Validated(ticket); return Task.FromResult(0); } }
Nell'esempio in alto, la validazione in ValidateClientAuthentication è un banale match di stringhe, ma in un'applicazione reale ovviamente dovremo effettuare una query su una base dati in cui abbiamo memorizzato le app registrate, così da verificare le credenziali in ingresso. Se il test ha successo, dobbiamo invocare il metodo Validated che marca il context come IsValidated consentendo al flusso di proseguire.
Il metodo successivo a essere invocato è GrantClientCredentials, in cui costruiamo il ClaimsIdentity. Nel codice precedente ci siamo limitati a specificare un unico claim, il nome, ma nulla vieta di indicarne di ulteriori, per implementare logiche autorizzative più complesse.
Se entrambi questi metodi hanno successo, il servizio Web API risponderà alla richiesta che abbiamo presentato a inizio script con un token di autorizzazione:
{ "access_token": "2L8KJld3Qj2....", "token_type": "bearer", "expires_in": 1209599, ".issued": "Sun, 21 Feb 2016 12:49:11 GMT", ".expires": "Sun, 06 Mar 2016 12:49:11 GMT" }
Questo token, potrà essere inviato - analogamente allo script precedente - nell'header di una richiesta a uno degli endpoint esposti dal nostro web service, affinché la richiesta possa essere validata e autorizzata:
GET /api/values HTTP/1.1 Host: localhost:15986 Content-Type: application/json Authorization: bearer 2L8KJld3Qj2.... Cache-Control: no-cache
Se a questo punto, utilizzando il debugger, mettiamo un breakpoint in ValuesController, potremo verificare che la proprietà User è effettivamente popolata con i claim che abbiamo rilasciato nello step di autenticazione.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Evitare il flickering dei componenti nel prerender di Blazor 8
Implementare il throttling in ASP.NET Core
Code scanning e advanced security con Azure DevOps
Utilizzare la libreria Benchmark.NET per misurare le performance
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Implementare l'infinite scroll con QuickGrid in Blazor Server
Utilizzare le Cache API di JavaScript per salvare elementi nella cache del browser
Short-circuiting della Pipeline in ASP.NET Core
Ottimizzare la latenza in Blazor 8 tramite InteractiveAuto render mode
Utilizzare il trigger SQL con le Azure Function
Creazione di plugin per Tailwind CSS: espandere le Funzionalità del Framework
Le novità di Angular: i miglioramenti alla CLI
I più letti di oggi
- Vuoi incontrare Bill Gates? Viaggia con ASPItalia.com!
- Customizzare il pager del DataGrid
- Stabilire un collegamento VPN tra una Web App e una Virtual Network
- Documentare ASP.NET Web API con Swagger
- Usare i servizi REST di BING per ottenere informazioni sulla posizione dell'utente
- Visual Studio 2005 CTP May