Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
4 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/app/unauthorized/unauthorized.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { UnauthorizedComponent } from './unauthorized.component';
4 |
5 | describe('UnauthorizedComponent', () => {
6 | let component: UnauthorizedComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ UnauthorizedComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(UnauthorizedComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/app/unauthorized/unauthorized.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-unauthorized',
5 | templateUrl: './unauthorized.component.html',
6 | styleUrls: ['./unauthorized.component.css']
7 | })
8 | export class UnauthorizedComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vip32/aspnetcore-keycloak/51c5433edefc54062e04dfd73e02ac7437baff8a/WebApp (angular)/ClientApp/src/assets/.gitkeep
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | production: false
8 | };
9 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | dotnet_angular_google_oidc
6 |
7 |
8 |
9 |
10 |
11 |
12 | Loading...
13 |
14 |
15 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | export function getBaseUrl() {
8 | return document.getElementsByTagName('base')[0].href;
9 | }
10 |
11 | const providers = [
12 | { provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] }
13 | ];
14 |
15 | if (environment.production) {
16 | enableProdMode();
17 | }
18 |
19 | platformBrowserDynamic(providers).bootstrapModule(AppModule)
20 | .catch(err => console.log(err));
21 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags.ts';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
3 | /* Provide sufficient contrast against white background */
4 | a {
5 | color: #0366d6;
6 | }
7 |
8 | code {
9 | color: #e01a76;
10 | }
11 |
12 | .btn-primary {
13 | color: #fff;
14 | background-color: #1b6ec2;
15 | border-color: #1861ac;
16 | }
17 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "types": []
6 | },
7 | "exclude": [
8 | "src/test.ts",
9 | "**/*.spec.ts"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/tsconfig.server.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs"
5 | },
6 | "angularCompilerOptions": {
7 | "entryModule": "app/app.server.module#AppServerModule"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "test.ts",
12 | "polyfills.ts"
13 | ],
14 | "include": [
15 | "**/*.spec.ts",
16 | "**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "module": "esnext",
6 | "outDir": "./dist/out-tsc",
7 | "sourceMap": true,
8 | "declaration": false,
9 | "moduleResolution": "node",
10 | "emitDecoratorMetadata": true,
11 | "experimentalDecorators": true,
12 | "target": "es2015",
13 | "typeRoots": [
14 | "node_modules/@types"
15 | ],
16 | "lib": [
17 | "es2017",
18 | "dom"
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/WebApp (angular)/ClientApp/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-shadowed-variable": true,
69 | "no-string-literal": false,
70 | "no-string-throw": true,
71 | "no-switch-case-fall-through": true,
72 | "no-trailing-whitespace": true,
73 | "no-unnecessary-initializer": true,
74 | "no-unused-expression": true,
75 | "no-use-before-declare": true,
76 | "no-var-keyword": true,
77 | "object-literal-sort-keys": false,
78 | "one-line": [
79 | true,
80 | "check-open-brace",
81 | "check-catch",
82 | "check-else",
83 | "check-whitespace"
84 | ],
85 | "prefer-const": true,
86 | "quotemark": [
87 | true,
88 | "single"
89 | ],
90 | "radix": true,
91 | "semicolon": [
92 | true,
93 | "always"
94 | ],
95 | "triple-equals": [
96 | true,
97 | "allow-null-check"
98 | ],
99 | "typedef-whitespace": [
100 | true,
101 | {
102 | "call-signature": "nospace",
103 | "index-signature": "nospace",
104 | "parameter": "nospace",
105 | "property-declaration": "nospace",
106 | "variable-declaration": "nospace"
107 | }
108 | ],
109 | "unified-signatures": true,
110 | "variable-name": false,
111 | "whitespace": [
112 | true,
113 | "check-branch",
114 | "check-decl",
115 | "check-operator",
116 | "check-separator",
117 | "check-type"
118 | ],
119 | "no-output-on-prefix": true,
120 | "no-inputs-metadata-property": true,
121 | "no-outputs-metadata-property": true,
122 | "no-host-metadata-property": true,
123 | "no-input-rename": true,
124 | "no-output-rename": true,
125 | "use-lifecycle-interface": true,
126 | "use-pipe-transform-interface": true,
127 | "component-class-suffix": true,
128 | "directive-class-suffix": true
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/WebApp (angular)/Controllers/ConfigController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Microsoft.AspNetCore.Mvc;
4 | using Microsoft.Extensions.Configuration;
5 | using System.Net.Http;
6 | using System.Net.Http.Headers;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Newtonsoft.Json;
9 | using Microsoft.Extensions.Hosting;
10 | using System.Linq;
11 |
12 | namespace WebApp__angular_.Controllers
13 | {
14 | [Route("api/config")]
15 | public class ConfigController : Controller
16 | {
17 | private readonly IConfiguration configuration;
18 | private readonly IWebHostEnvironment environment;
19 |
20 | private OidcWellKnown wellKnown;
21 | private JwtKs _jwtKs;
22 |
23 | public ConfigController(IConfiguration config, IWebHostEnvironment environment)
24 | {
25 | this.configuration = config;
26 | this.environment = environment;
27 | }
28 |
29 | [HttpGet(".well-known/openid-configuration")]
30 | public async Task WellKnownAsync()
31 | {
32 | Console.WriteLine("GET .well-known/openid-configuration");
33 | var protocol = this.Request.IsHttps ? "https://" : "http://";
34 | var jwks_uri = $"{protocol}{this.Request.Host.ToUriComponent()}/api/config/discovery/keys";
35 | var wellKnown = await this.GetWellKnownAsync().ConfigureAwait(false);
36 | wellKnown.jwks_uri = jwks_uri;
37 | return wellKnown;
38 | }
39 |
40 | [HttpGet("discovery/keys")]
41 | public async Task KeysAsync()
42 | {
43 | return await this.GetJwtKs().ConfigureAwait(false);
44 | }
45 |
46 | [HttpGet("profile")]
47 | public async Task Profile()
48 | {
49 | return HttpContext.User?.Claims?.Select(h => $"CLAIM {h.Type}: {h.Value}").Aggregate((i, j) => i + " | " + j);
50 | }
51 |
52 | [HttpGet("configuration")]
53 | public async Task ConfigurationAsync()
54 | {
55 | Console.WriteLine("GET configuration");
56 | var config = new OidcConfig();
57 | var wellKnown = await this.GetWellKnownAsync().ConfigureAwait(false);
58 |
59 | var protocol = this.Request.IsHttps ? "https://" : "http://";
60 | config.stsServer = $"{protocol}{this.Request.Host.ToUriComponent()}/api/config";
61 | config.redirect_url = $"{protocol}{this.Request.Host.ToUriComponent()}/";
62 | config.client_id = this.configuration["Oidc:ClientId"];
63 | config.response_type = "id_token token";
64 | if (!String.IsNullOrEmpty(this.configuration["Oidc:Scope"]))
65 | {
66 | config.scope = this.configuration["Oidc:Scope"];
67 | }
68 | else
69 | {
70 | config.scope = "openid profile email claims";
71 | }
72 | config.post_logout_redirect_uri = $"{protocol}{this.Request.Host.ToUriComponent()}/";
73 | config.post_login_route = "/home";
74 | config.forbidden_route = "/home";
75 | config.unauthorized_route = "/home";
76 | config.auto_userinfo = false;
77 | config.log_console_warning_active = true;
78 | config.log_console_debug_active = this.environment.IsDevelopment();
79 | config.max_id_token_iat_offset_allowed_in_seconds = 1000;
80 | if (!String.IsNullOrEmpty(this.configuration["Oidc:Resource"]))
81 | {
82 | config.additional_login_parameters["resource"] = this.configuration["Oidc:Resource"];
83 | }
84 | if (!String.IsNullOrEmpty(this.configuration["Oidc:Prompt"]))
85 | {
86 | config.additional_login_parameters["prompt"] = this.configuration["Oidc:Prompt"];
87 | }
88 | return config;
89 | }
90 |
91 | private async Task GetWellKnownAsync()
92 | {
93 | if (this.wellKnown == null)
94 | {
95 | var client = new HttpClient();
96 | client.BaseAddress = new Uri(this.configuration["Oidc:Authority"] + "/");
97 | client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
98 |
99 | var response = await client.GetAsync(".well-known/openid-configuration").ConfigureAwait(false);
100 | if (response.IsSuccessStatusCode)
101 | {
102 | var wellknownString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
103 | this.wellKnown = JsonConvert.DeserializeObject(wellknownString);
104 | }
105 | }
106 | return this.wellKnown;
107 | }
108 |
109 | private async Task GetJwtKs()
110 | {
111 | if (this._jwtKs == null)
112 | {
113 | var client = new HttpClient();
114 | var wellKnown = await this.GetWellKnownAsync().ConfigureAwait(false);
115 | client.BaseAddress = new Uri(wellKnown.jwks_uri);
116 | client.DefaultRequestHeaders.Clear();
117 | client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
118 |
119 | var response = await client.GetAsync("").ConfigureAwait(false);
120 | if (response.IsSuccessStatusCode)
121 | {
122 | var jwrkstring = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
123 | this._jwtKs = JsonConvert.DeserializeObject(jwrkstring);
124 | }
125 | }
126 |
127 | return this._jwtKs;
128 | }
129 | }
130 | }
--------------------------------------------------------------------------------
/WebApp (angular)/Controllers/WeatherForecastController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace WebApp__angular_.Controllers
9 | {
10 | [ApiController]
11 | [Route("[controller]")]
12 | public class WeatherForecastController : ControllerBase
13 | {
14 | private static readonly string[] Summaries = new[]
15 | {
16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
17 | };
18 |
19 | private readonly ILogger _logger;
20 |
21 | public WeatherForecastController(ILogger logger)
22 | {
23 | _logger = logger;
24 | }
25 |
26 | [HttpGet]
27 | public IEnumerable Get()
28 | {
29 | var rng = new Random();
30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast
31 | {
32 | Date = DateTime.Now.AddDays(index),
33 | TemperatureC = rng.Next(-20, 55),
34 | Summary = Summaries[rng.Next(Summaries.Length)]
35 | })
36 | .ToArray();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/WebApp (angular)/Model/OidcModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace WebApp__angular_
4 | {
5 | public class OidcConfig
6 | {
7 | public string stsServer { get; set; }
8 | public string redirect_url { get; set; }
9 | public string client_id { get; set; }
10 | public string response_type { get; set; }
11 | public string scope { get; set; }
12 | public string post_logout_redirect_uri { get; set; }
13 | public string post_login_route { get; set; }
14 | public bool start_checksession { get; set; }
15 | public bool silent_renew { get; set; }
16 | public string silent_renew_url { get; set; }
17 | public string startup_route { get; set; }
18 | public string forbidden_route { get; set; }
19 | public string unauthorized_route { get; set; }
20 | public bool auto_userinfo { get; set; }
21 | public bool log_console_warning_active { get; set; }
22 | public bool log_console_debug_active { get; set; }
23 | public int max_id_token_iat_offset_allowed_in_seconds { get; set; }
24 | public Dictionary additional_login_parameters { get; } = new Dictionary();
25 | }
26 |
27 | public class OidcWellKnown
28 | {
29 | public string authorization_endpoint { get; set; }
30 | public string token_endpoint { get; set; }
31 | public List token_endpoint_auth_methods_supported { get; set; }
32 | public string jwks_uri { get; set; }
33 | public List response_modes_supported { get; set; }
34 | public List subject_types_supported { get; set; }
35 | public List id_token_signing_alg_values_supported { get; set; }
36 | public bool http_logout_supported { get; set; }
37 | public bool frontchannel_logout_supported { get; set; }
38 | public string end_session_endpoint { get; set; }
39 | public List response_types_supported { get; set; }
40 | public List scopes_supported { get; set; }
41 | public string issuer { get; set; }
42 | public List claims_supported { get; set; }
43 | public bool request_uri_parameter_supported { get; set; }
44 | public string tenant_region_scope { get; set; }
45 | public string cloud_instance_name { get; set; }
46 | public string cloud_graph_host_name { get; set; }
47 | public string msgraph_host { get; set; }
48 | public string rbac_url { get; set; }
49 | }
50 |
51 | public class JwtKey
52 | {
53 | public string kty { get; set; }
54 | public string use { get; set; }
55 | public string kid { get; set; }
56 | public string x5t { get; set; }
57 | public string n { get; set; }
58 | public string e { get; set; }
59 | public List x5c { get; set; }
60 | public string issuer { get; set; }
61 | }
62 |
63 | public class JwtKs
64 | {
65 | public List keys { get; set; }
66 | }
67 | }
--------------------------------------------------------------------------------
/WebApp (angular)/Pages/Error.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model ErrorModel
3 | @{
4 | ViewData["Title"] = "Error";
5 | }
6 |
7 |
Error.
8 |
An error occurred while processing your request.
9 |
10 | @if (Model.ShowRequestId)
11 | {
12 |
13 | Request ID:@Model.RequestId
14 |
15 | }
16 |
17 |
Development Mode
18 |
19 | Swapping to the Development environment displays detailed information about the error that occurred.
20 |
21 |
22 | The Development environment shouldn't be enabled for deployed applications.
23 | It can result in displaying sensitive information from exceptions to end users.
24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
25 | and restarting the app.
26 |