OAuth 2.0 is about authorization: it issues an access token for accessing an API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // ====================================================================== // Q: OAuth 2.0 vs OpenID Connect. Which flow do you use when? // // OAuth 2.0 is about authorization: it issues an access token for accessing an // API. OpenID Connect builds on top of it and adds authentication: the id_token // says who the user is. // - Authorization Code + PKCE: users (web apps, SPA, mobile). The default today. // - Client Credentials: service-to-service without a user: background jobs, // integration with Salesforce or an ERP. // - Device Code: devices without a browser (CLI, IoT, e-mobility chargers). // - Implicit, Password (ROPC): deprecated, we don't use them. // Between our own services in Azure: Managed Identity, with no secret at all. // ====================================================================== // Client credentials to an external API, with token caching (MSAL keeps a cache, so singleton) builder.Services.AddSingleton(sp => { var o = builder.Configuration.GetSection("Erp").Get<ErpAuthOptions>()!; return ConfidentialClientApplicationBuilder.Create(o.ClientId) .WithClientSecret(o.ClientSecret) // from Key Vault (Q15). Better: certificate .WithAuthority(o.Authority) .Build(); }); public class ErpTokenHandler(IConfidentialClientApplication msal, IOptions<ErpAuthOptions> opt) : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct) { var result = await msal.AcquireTokenForClient([opt.Value.Scope]).ExecuteAsync(ct); // from cache if still valid req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); return await base.SendAsync(req, ct); } } builder.Services.AddTransient<ErpTokenHandler>(); builder.Services.AddHttpClient<IErpClient, ErpClient>().AddHttpMessageHandler<ErpTokenHandler>(); |