88using Microsoft . AspNetCore . Hosting ;
99using Microsoft . AspNetCore . Http ;
1010using Microsoft . AspNetCore . Routing ;
11+ using Microsoft . Extensions . Configuration ;
1112using Microsoft . Extensions . DependencyInjection ;
1213using Microsoft . Extensions . Hosting ;
1314using Microsoft . IdentityModel . Tokens ;
@@ -17,11 +18,17 @@ namespace Microsoft.SCIM.WebHostSample
1718{
1819 public class Startup
1920 {
21+ private readonly IWebHostEnvironment _env ;
22+ private readonly IConfiguration _configuration ;
23+
2024 public IMonitor MonitoringBehavior { get ; set ; }
2125 public IProvider ProviderBehavior { get ; set ; }
2226
23- public Startup ( )
27+ public Startup ( IWebHostEnvironment env , IConfiguration configuration )
2428 {
29+ this . _env = env ;
30+ this . _configuration = configuration ;
31+
2532 this . MonitoringBehavior = new ConsoleMonitor ( ) ;
2633 this . ProviderBehavior = new InMemoryProvider ( ) ;
2734 }
@@ -30,26 +37,62 @@ public Startup()
3037 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
3138 public void ConfigureServices ( IServiceCollection services )
3239 {
33- services . AddAuthentication ( options =>
40+ if ( _env . IsDevelopment ( ) )
3441 {
35- options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
36- options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
37- options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
38- } )
39- . AddJwtBearer ( options =>
42+ // Development environment code
43+ // Validation for bearer token for authorization used during testing.
44+ // NOTE: It's not recommended to use this code in production, it is not meant to replace proper OAuth authentication.
45+ // This option is primarily available for testing purposes.
46+ services . AddAuthentication ( options =>
4047 {
41- options . TokenValidationParameters =
42- new TokenValidationParameters
48+ options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
49+ options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
50+ options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
51+ } )
52+ . AddJwtBearer ( options =>
53+ {
54+ options . TokenValidationParameters =
55+ new TokenValidationParameters
56+ {
57+ ValidateIssuer = false ,
58+ ValidateAudience = false ,
59+ ValidateLifetime = false ,
60+ ValidateIssuerSigningKey = false ,
61+ ValidIssuer = this . _configuration [ "Token:TokenIssuer" ] ,
62+ ValidAudience = this . _configuration [ "Token:TokenAudience" ] ,
63+ IssuerSigningKey = new SymmetricSecurityKey ( Encoding . UTF8 . GetBytes ( this . _configuration [ "Token:IssuerSigningKey" ] ) )
64+ } ;
65+ } ) ;
66+ }
67+ else
68+ {
69+ // Leave the optional Secret Token field blank
70+ // Azure AD includes an OAuth bearer token issued from Azure AD with each request
71+ // The following code validates the Azure AD-issued token
72+ // NOTE: It's not recommended to leave this field blank and rely on a token generated by Azure AD.
73+ // This option is primarily available for testing purposes.
74+ services . AddAuthentication ( options =>
75+ {
76+ options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
77+ options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
78+ options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
79+ } )
80+ . AddJwtBearer ( options =>
81+ {
82+ options . Authority = this . _configuration [ "Token:TokenIssuer" ] ;
83+ options . Audience = this . _configuration [ "Token:TokenAudience" ] ;
84+ options . Events = new JwtBearerEvents
4385 {
44- ValidateIssuer = false ,
45- ValidateAudience = false ,
46- ValidateLifetime = false ,
47- ValidateIssuerSigningKey = false ,
48- ValidIssuer = ServiceConstants . TokenIssuer ,
49- ValidAudience = ServiceConstants . TokenAudience ,
50- IssuerSigningKey = new SymmetricSecurityKey ( Encoding . UTF8 . GetBytes ( ServiceConstants . TokenIssuer ) )
86+ OnTokenValidated = context =>
87+ {
88+ // NOTE: You can optionally take action when the OAuth 2.0 bearer token was validated.
89+
90+ return Task . CompletedTask ;
91+ } ,
92+ OnAuthenticationFailed = AuthenticationFailed
5193 } ;
52- } ) ;
94+ } ) ;
95+ }
5396
5497 services . AddControllers ( ) . AddNewtonsoftJson ( ) ;
5598
@@ -58,9 +101,9 @@ public void ConfigureServices(IServiceCollection services)
58101 }
59102
60103 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
61- public void Configure ( IApplicationBuilder app , IWebHostEnvironment env )
104+ public void Configure ( IApplicationBuilder app )
62105 {
63- if ( env . IsDevelopment ( ) )
106+ if ( _env . IsDevelopment ( ) )
64107 {
65108 app . UseDeveloperExceptionPage ( ) ;
66109 }
@@ -78,5 +121,16 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
78121 endpoints . MapDefaultControllerRoute ( ) ;
79122 } ) ;
80123 }
124+
125+ private Task AuthenticationFailed ( AuthenticationFailedContext arg )
126+ {
127+ // For debugging purposes only!
128+ var s = $ "{{AuthenticationFailed: '{ arg . Exception . Message } '}}";
129+
130+ arg . Response . ContentLength = s . Length ;
131+ arg . Response . Body . WriteAsync ( Encoding . UTF8 . GetBytes ( s ) , 0 , s . Length ) ;
132+
133+ return Task . FromException ( arg . Exception ) ;
134+ }
81135 }
82136}
0 commit comments