Authentication
OAuth: Client Credentials
- Used by clients to obtain an access token outside of the context of the user
- No user login prompt
- The client credentials are passed directly
curl --location --request GET 'https://login.microsoftonline.com/tenant-id/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--form 'grant_type="client_credentials"' \
--form 'client_id="client-id"' \
--form 'client_secret="client-secret"' \
--form 'resource="https://storage.azure.com"' # The protected resource (a access token is valid only for this resource)
- In order to access a resource, you must pass the access token under the
Authorization header and the api version under x-ms-version (E.g., 2017-11-09)
# resource="https://storage.azure.com"
curl --location --request GET 'https://hvitoi.blob.core.windows.net/{container-name}/sample.txt' \
--header 'Authorization: Bearer bearer-token' \
--header 'x-ms-version: 2017-11-09'
# resource="https://vault.azure.net"
curl --location --request GET 'https://hvitoi.vault.azure.net/secrets/{secret-name}/{secret-version}?api-version=7.1' \
--header 'Authorization: Bearer bearer-token' \
--header 'x-ms-version: 2017-11-09'
# resource="https://graph.microsoft.com"
curl --location --request GET 'https://graph.microsoft.com/v1.0/users' \
--header 'Authorization: Bearer bearer-token' # Retrieve data about all AD users
Microsoft Authentication Library
- Library:
- Allow developers to acquire tokens from the Microsoft Identity Platform
- You don't need to directly work with OAuth libraries in yor code
- Fetch tokens on behalf of the user or application
- Maintains a token cache and refreshes when they are about to expire
- The redirect URI must be specified at the
Application Object under Manage/Authentication tab
- Add a platform configuration: web, single-page, android, desktop, etc
- E.g., https://localhost:44366/signin-oidc (login)
- E.g., https://localhost:44366/signout-oidc (logout)
<ItemGroup>
<!-- Basic connectivity with MS Identity Platform -->
<PackageReference Include="Microsoft.Identity.Web" Version="1.9.2" />
<!-- Graphic screen prompt for login -->
<PackageReference Include="Microsoft.Identity.Web.UI" Version="1.9.2" />
<!-- Policy builder authorization -->
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.13" />
<!-- User interface for signin/signout -->
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.1.13" />
</ItemGroup>
// appsettings.json
{
"AllowedHosts": "*",
"AzureAd": {
"Instance": "https://login.microsoftonline.com/", // authorization server
"TenantId": "tenant-id",
"ClientId": "client-id",
"CallbackPath": "/signin-oidc", // route that receives the code (redirect uri )
"SignedOutCallbackPath": "/signout-oidc"
},
"ConnectionStrings": {
"OAuth_2ContextConnection": "Data Source=OAuth-2.db"
}
}
public class Startup
{
public Startup(IConfiguration configuration) { Configuration configuration; }
public IConfiguration Configuration { get; }
// Add services to the container
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// Set up scope of access that the consent screen will ask to the user (not necessary for ID tokens)
string[] scopes = new string[] { "https://storage.azure.com/user_impersonation" }; // user_impersonation: use all roles assigned to the logged in user
// "AzureAd" stores the configuration to connect to the authorization server
services
.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(scopes)
.AddInMemoryTokenCaches();
services.AddRazorPages().AddMvcOptions(options =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI(); // user interface for signin/out
}
// Configure the HTTP request pipeline
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication(); // protects the page
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Open ID Connect
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "https://login.microsoftonline.com/{tenant-id}";
options.ClientId = "{client-id}";
options.ResponseType = OpenIdConnectResponseType.Code;
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.SaveTokens = true;
options.Scope.Add("profile");
options.Scope.Add("openid");
options.ClientSecret = "{client-secret}";
});
}