Skip to content

Commit

Permalink
[Azure] [Fixes dotnet#6033, dotnet#6580, dotnet#6669] Various fixes a…
Browse files Browse the repository at this point in the history
…nd cleanups.

* Adds an Azure AD Sample and adds a page to test access denied.
* Renames AzureAD and AzureADB2C internal classes for easier to debug
  stacktraces.
* Fixes service registration for options configuration.
* Adds missing deps to the solution.
  • Loading branch information
javiercn committed Feb 25, 2019
1 parent a3e0a45 commit 23c528c
Show file tree
Hide file tree
Showing 66 changed files with 23,688 additions and 36 deletions.
45 changes: 45 additions & 0 deletions src/Azure/Azure.sln
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authen
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication", "..\Security\Authentication\Core\src\Microsoft.AspNetCore.Authentication.csproj", "{A5E7BA46-B76B-467A-88FA-38E04D0A42FC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureADSample", "AzureAD\samples\AzureADSample\AzureADSample.csproj", "{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.Cookies", "..\Security\Authentication\Cookies\src\Microsoft.AspNetCore.Authentication.Cookies.csproj", "{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Authentication.JwtBearer", "..\Security\Authentication\JwtBearer\src\Microsoft.AspNetCore.Authentication.JwtBearer.csproj", "{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -425,6 +431,42 @@ Global
{A5E7BA46-B76B-467A-88FA-38E04D0A42FC}.Release|x64.Build.0 = Release|Any CPU
{A5E7BA46-B76B-467A-88FA-38E04D0A42FC}.Release|x86.ActiveCfg = Release|Any CPU
{A5E7BA46-B76B-467A-88FA-38E04D0A42FC}.Release|x86.Build.0 = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|x64.ActiveCfg = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|x64.Build.0 = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|x86.ActiveCfg = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Debug|x86.Build.0 = Debug|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|Any CPU.Build.0 = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|x64.ActiveCfg = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|x64.Build.0 = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|x86.ActiveCfg = Release|Any CPU
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9}.Release|x86.Build.0 = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|x64.ActiveCfg = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|x64.Build.0 = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|x86.ActiveCfg = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Debug|x86.Build.0 = Debug|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|Any CPU.Build.0 = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|x64.ActiveCfg = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|x64.Build.0 = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|x86.ActiveCfg = Release|Any CPU
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD}.Release|x86.Build.0 = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|x64.ActiveCfg = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|x64.Build.0 = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|x86.ActiveCfg = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Debug|x86.Build.0 = Debug|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|Any CPU.Build.0 = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|x64.ActiveCfg = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|x64.Build.0 = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|x86.ActiveCfg = Release|Any CPU
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -463,6 +505,9 @@ Global
{F44054A2-DAC9-467F-B899-F35F9DCDAE9C} = {84622717-F98A-4DE2-806E-1EF89C45C0EB}
{406DF28A-0B58-408E-96B0-2D373EE36352} = {84622717-F98A-4DE2-806E-1EF89C45C0EB}
{A5E7BA46-B76B-467A-88FA-38E04D0A42FC} = {84622717-F98A-4DE2-806E-1EF89C45C0EB}
{8B083F30-7199-4BE1-97B0-2C57FE0C25E9} = {A28A64CA-297E-4023-895A-483DFDA59FBE}
{58BAE6BE-7BEB-4C1B-8863-5BF51D4134BD} = {84622717-F98A-4DE2-806E-1EF89C45C0EB}
{B2499B17-5D03-4A5B-9AD1-DBFE7C4B08DF} = {84622717-F98A-4DE2-806E-1EF89C45C0EB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {81AADD49-473B-43ED-8A08-F6B7A058AA39}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public static AuthenticationBuilder AddAzureADBearer(

builder.Services.Configure(TryAddJwtBearerSchemeMapping(scheme, jwtBearerScheme));

builder.Services.TryAddSingleton<IConfigureOptions<AzureADOptions>, AzureADOptionsConfiguration>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<AzureADOptions>, AzureADOptionsConfiguration>());

builder.Services.TryAddSingleton<IConfigureOptions<JwtBearerOptions>, JwtBearerOptionsConfiguration>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<JwtBearerOptions>, AzureADJwtBearerOptionsConfiguration>());

builder.Services.Configure(scheme, configureOptions);
builder.AddJwtBearer(jwtBearerScheme, o => { });
Expand Down Expand Up @@ -113,11 +113,11 @@ public static AuthenticationBuilder AddAzureAD(

builder.Services.Configure(TryAddOpenIDCookieSchemeMappings(scheme, openIdConnectScheme, cookieScheme));

builder.Services.TryAddSingleton<IConfigureOptions<AzureADOptions>, AzureADOptionsConfiguration>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<AzureADOptions>, AzureADOptionsConfiguration>());

builder.Services.TryAddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsConfiguration>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<OpenIdConnectOptions>, AzureADOpenIdConnectOptionsConfiguration>());

builder.Services.TryAddSingleton<IConfigureOptions<CookieAuthenticationOptions>, CookieOptionsConfiguration>();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<CookieAuthenticationOptions>, AzureADCookieOptionsConfiguration>());

builder.Services.Configure(scheme, configureOptions);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

namespace Microsoft.AspNetCore.Authentication.AzureAD.UI
{
internal class CookieOptionsConfiguration : IConfigureNamedOptions<CookieAuthenticationOptions>
internal class AzureADCookieOptionsConfiguration : IConfigureNamedOptions<CookieAuthenticationOptions>
{
private readonly IOptions<AzureADSchemeOptions> _schemeOptions;
private readonly IOptionsMonitor<AzureADOptions> _AzureADOptions;

public CookieOptionsConfiguration(IOptions<AzureADSchemeOptions> schemeOptions, IOptionsMonitor<AzureADOptions> AzureADOptions)
public AzureADCookieOptionsConfiguration(IOptions<AzureADSchemeOptions> schemeOptions, IOptionsMonitor<AzureADOptions> AzureADOptions)
{
_schemeOptions = schemeOptions;
_AzureADOptions = AzureADOptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization;

using System;
Expand All @@ -8,12 +8,12 @@

namespace Microsoft.AspNetCore.Authentication
{
internal class JwtBearerOptionsConfiguration : IConfigureNamedOptions<JwtBearerOptions>
internal class AzureADJwtBearerOptionsConfiguration : IConfigureNamedOptions<JwtBearerOptions>
{
private readonly IOptions<AzureADSchemeOptions> _schemeOptions;
private readonly IOptionsMonitor<AzureADOptions> _azureADOptions;

public JwtBearerOptionsConfiguration(
public AzureADJwtBearerOptionsConfiguration(
IOptions<AzureADSchemeOptions> schemeOptions,
IOptionsMonitor<AzureADOptions> azureADOptions)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization;

using System;
Expand All @@ -7,12 +7,12 @@

namespace Microsoft.AspNetCore.Authentication.AzureAD.UI
{
internal class OpenIdConnectOptionsConfiguration : IConfigureNamedOptions<OpenIdConnectOptions>
internal class AzureADOpenIdConnectOptionsConfiguration : IConfigureNamedOptions<OpenIdConnectOptions>
{
private readonly IOptions<AzureADSchemeOptions> _schemeOptions;
private readonly IOptionsMonitor<AzureADOptions> _azureADOptions;

public OpenIdConnectOptionsConfiguration(IOptions<AzureADSchemeOptions> schemeOptions, IOptionsMonitor<AzureADOptions> azureADOptions)
public AzureADOpenIdConnectOptionsConfiguration(IOptions<AzureADSchemeOptions> schemeOptions, IOptionsMonitor<AzureADOptions> azureADOptions)
{
_schemeOptions = schemeOptions;
_azureADOptions = azureADOptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization;

using System;
Expand Down Expand Up @@ -76,6 +76,98 @@ public void AddAzureAD_ConfiguresAllOptions()
Assert.Equal(AzureADDefaults.CookieScheme, openIdOptions.SignInScheme);
}

[Fact]
public void AddAzureAD_AllowsOverridingCookiesAndOpenIdConnectSettings()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());

// Act
services.AddAuthentication()
.AddAzureAD(o =>
{
o.Instance = "https://login.microsoftonline.com";
o.ClientId = "ClientId";
o.ClientSecret = "ClientSecret";
o.CallbackPath = "/signin-oidc";
o.Domain = "domain.onmicrosoft.com";
o.TenantId = "Common";
});

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, o =>
{
o.Authority = "https://overriden.com";
});

services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, o =>
{
o.AccessDeniedPath = "/Overriden";
});

var provider = services.BuildServiceProvider();

// Assert
var openIdOptionsMonitor = provider.GetService<IOptionsMonitor<OpenIdConnectOptions>>();
Assert.NotNull(openIdOptionsMonitor);
var openIdOptions = openIdOptionsMonitor.Get(AzureADDefaults.OpenIdScheme);
Assert.Equal("ClientId", openIdOptions.ClientId);
Assert.Equal($"https://overriden.com", openIdOptions.Authority);

var cookieAuthenticationOptionsMonitor = provider.GetService<IOptionsMonitor<CookieAuthenticationOptions>>();
Assert.NotNull(cookieAuthenticationOptionsMonitor);
var cookieAuthenticationOptions = cookieAuthenticationOptionsMonitor.Get(AzureADDefaults.CookieScheme);
Assert.Equal("/AzureAD/Account/SignIn/AzureAD", cookieAuthenticationOptions.LoginPath);
Assert.Equal("/Overriden", cookieAuthenticationOptions.AccessDeniedPath);
}

[Fact]
public void AddAzureAD_RegisteringAddCookiesAndAddOpenIdConnectHasNoImpactOnAzureAAExtensions()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());

// Act
services.AddAuthentication()
.AddOpenIdConnect()
.AddCookie()
.AddAzureAD(o =>
{
o.Instance = "https://login.microsoftonline.com";
o.ClientId = "ClientId";
o.ClientSecret = "ClientSecret";
o.CallbackPath = "/signin-oidc";
o.Domain = "domain.onmicrosoft.com";
o.TenantId = "Common";
});

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, o =>
{
o.Authority = "https://overriden.com";
});

services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, o =>
{
o.AccessDeniedPath = "/Overriden";
});

var provider = services.BuildServiceProvider();

// Assert
var openIdOptionsMonitor = provider.GetService<IOptionsMonitor<OpenIdConnectOptions>>();
Assert.NotNull(openIdOptionsMonitor);
var openIdOptions = openIdOptionsMonitor.Get(AzureADDefaults.OpenIdScheme);
Assert.Equal("ClientId", openIdOptions.ClientId);
Assert.Equal($"https://overriden.com", openIdOptions.Authority);

var cookieAuthenticationOptionsMonitor = provider.GetService<IOptionsMonitor<CookieAuthenticationOptions>>();
Assert.NotNull(cookieAuthenticationOptionsMonitor);
var cookieAuthenticationOptions = cookieAuthenticationOptionsMonitor.Get(AzureADDefaults.CookieScheme);
Assert.Equal("/AzureAD/Account/SignIn/AzureAD", cookieAuthenticationOptions.LoginPath);
Assert.Equal("/Overriden", cookieAuthenticationOptions.AccessDeniedPath);
}

[Fact]
public void AddAzureAD_ThrowsForDuplicatedSchemes()
{
Expand Down Expand Up @@ -197,6 +289,73 @@ public void AddAzureADBearer_ConfiguresAllOptions()
Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
}

[Fact]
public void AddAzureADBearer_CanOverrideJwtBearerOptionsConfiguration()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());

// Act
services.AddAuthentication()
.AddAzureADBearer(o =>
{
o.Instance = "https://login.microsoftonline.com/";
o.ClientId = "ClientId";
o.CallbackPath = "/signin-oidc";
o.Domain = "domain.onmicrosoft.com";
o.TenantId = "TenantId";
});

services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, o =>
{
o.Audience = "http://overriden.com";
});

var provider = services.BuildServiceProvider();

// Assert
var bearerOptionsMonitor = provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
Assert.NotNull(bearerOptionsMonitor);
var bearerOptions = bearerOptionsMonitor.Get(AzureADDefaults.JwtBearerAuthenticationScheme);
Assert.Equal("http://overriden.com", bearerOptions.Audience);
Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
}

[Fact]
public void AddAzureADBearer_RegisteringJwtBearerHasNoImpactOnAzureAAExtensions()
{
// Arrange
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());

// Act
services.AddAuthentication()
.AddJwtBearer()
.AddAzureADBearer(o =>
{
o.Instance = "https://login.microsoftonline.com/";
o.ClientId = "ClientId";
o.CallbackPath = "/signin-oidc";
o.Domain = "domain.onmicrosoft.com";
o.TenantId = "TenantId";
});

services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, o =>
{
o.Audience = "http://overriden.com";
});

var provider = services.BuildServiceProvider();

// Assert
var bearerOptionsMonitor = provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
Assert.NotNull(bearerOptionsMonitor);
var bearerOptions = bearerOptionsMonitor.Get(AzureADDefaults.JwtBearerAuthenticationScheme);
Assert.Equal("http://overriden.com", bearerOptions.Audience);
Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
}

[Fact]
public void AddAzureADBearer_ThrowsForDuplicatedSchemes()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

namespace Microsoft.AspNetCore.Authentication.AzureADB2C.UI
{
internal class CookieOptionsConfiguration : IConfigureNamedOptions<CookieAuthenticationOptions>
internal class AzureADB2CCookieOptionsConfiguration : IConfigureNamedOptions<CookieAuthenticationOptions>
{
private readonly IOptions<AzureADB2CSchemeOptions> _schemeOptions;
private readonly IOptionsMonitor<AzureADB2COptions> _azureADB2COptions;

public CookieOptionsConfiguration(IOptions<AzureADB2CSchemeOptions> schemeOptions, IOptionsMonitor<AzureADB2COptions> azureADB2COptions)
public AzureADB2CCookieOptionsConfiguration(IOptions<AzureADB2CSchemeOptions> schemeOptions, IOptionsMonitor<AzureADB2COptions> azureADB2COptions)
{
_schemeOptions = schemeOptions;
_azureADB2COptions = azureADB2COptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization;

using Microsoft.AspNetCore.Authentication.JwtBearer;
Expand All @@ -7,12 +7,12 @@

namespace Microsoft.AspNetCore.Authentication
{
internal class JwtBearerOptionsConfiguration : IConfigureNamedOptions<JwtBearerOptions>
internal class AzureADB2CJwtBearerOptionsConfiguration : IConfigureNamedOptions<JwtBearerOptions>
{
private readonly IOptions<AzureADB2CSchemeOptions> _schemeOptions;
private readonly IOptionsMonitor<AzureADB2COptions> _azureADB2COptions;

public JwtBearerOptionsConfiguration(
public AzureADB2CJwtBearerOptionsConfiguration(
IOptions<AzureADB2CSchemeOptions> schemeOptions,
IOptionsMonitor<AzureADB2COptions> azureADB2COptions)
{
Expand All @@ -30,7 +30,7 @@ public void Configure(string name, JwtBearerOptions options)
}

options.Audience = azureADB2COptions.ClientId;
options.Authority = OpenIdConnectOptionsConfiguration.BuildAuthority(azureADB2COptions);
options.Authority = AzureADB2COpenIdConnectOptionsConfiguration.BuildAuthority(azureADB2COptions);
}

public void Configure(JwtBearerOptions options)
Expand Down
Loading

0 comments on commit 23c528c

Please sign in to comment.