[ApiAuth] Switches back to use code+PKCE (#12375)

* Move SPA flows to use code + pkce
* Updates OIDC dependency to 1.9-beta1
This commit is contained in:
Javier Calvarro Nelson 2019-07-20 13:06:53 +02:00 committed by GitHub
parent d8911c1c74
commit 7bf660947b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1951 additions and 920 deletions

View File

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.ApiAuthorization.IdentityServer;
using Microsoft.AspNetCore.Mvc;
namespace ApiAuthSample.Controllers
{
public class ConfigurationController : ControllerBase
{
private readonly IClientRequestParametersProvider _clientRequestParametersProvider;
public ConfigurationController(IClientRequestParametersProvider clientRequestParametersProvider)
{
_clientRequestParametersProvider = clientRequestParametersProvider;
}
[HttpGet("/_configuration/{clientId}")]
public IActionResult GetClientParameters(string clientId)
{
var parameters = _clientRequestParametersProvider.GetClientParameters(HttpContext, clientId);
if (parameters == null)
{
return BadRequest($"Parameters for client '{clientId}' not found.");
}
else
{
return Ok(parameters);
}
}
}
}

View File

@ -14,21 +14,15 @@
</head>
<body>
<h1>ApiAuthSample SPA client</h1>
<button id="login">Login</button>
<button id="login" disabled>Login</button>
<button id="logout" disabled>Logout</button>
<button id="call-api" disabled>Call API</button>
<div id="login-result"></div>
<div id="api-result"></div>
<script src="/js/oidc-client.js"></script>
<script id="apiauth" type="text/javascript" asp-apiauth-parameters="ApiAuthSampleSPA">
let $data = document.querySelector("#apiauth");
let configuration = {};
for (let key in $data.dataset) {
configuration[key] = $data.dataset[key];
}
let mgr = new Oidc.UserManager(configuration);
</script>
<script src="js/app.js"></script>
<script id="apiauth" type="text/javascript">
initializeApplication();
</script>
</body>
</html>

View File

@ -1,4 +1,13 @@

var ids = {
login: 'login',
logout: 'logout',
callApi: 'call-api',
loginResult: 'login-result',
apiResults: 'api-result'
};
let mgr = undefined;
function invokeLogin() {
// Redirects to the Authorization Server for sign in.
return mgr.signinRedirect();
@ -43,19 +52,14 @@ async function callApi() {
// Code to update the UI
if (window.location.hash) {
handleAuthorizationServerCallback();
window.location.hash = '';
if (window.location.hash || window.location.search) {
initializeApplication()
.then(() => {
handleAuthorizationServerCallback();
window.location.hash = '';
});
}
let ids = {
login: 'login',
logout: 'logout',
callApi: 'call-api',
loginResult: 'login-result',
apiResults: 'api-result'
};
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
let login = document.getElementById(ids.login);
@ -68,6 +72,20 @@ document.onreadystatechange = function () {
}
};
async function initializeApplication() {
const response = await fetch('_configuration/ApiAuthSampleSPA');
const configuration = await response.json();
mgr = new Oidc.UserManager(configuration);
enableLoginButton();
function enableLoginButton() {
const login = document.querySelector('#login');
login.disabled = false;
}
}
function updateUserUI(user, error) {
let loginResults = document.getElementById(ids.loginResult);
let heading = document.createElement('h2');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -38,8 +38,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
case ApplicationProfiles.IdentityServerSPA:
case ApplicationProfiles.SPA:
responseType = "id_token token";
break;
case ApplicationProfiles.NativeApp:
responseType = "code";
break;

View File

@ -28,7 +28,9 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.IdentityServerSPA)
.WithAllowedGrants(GrantTypes.Implicit)
.WithAllowedGrants(GrantTypes.Code)
.WithoutClientSecrets()
.WithPkce()
.WithAllowedOrigins(Array.Empty<string>())
.AllowAccessTokensViaBrowser();
}
@ -43,7 +45,9 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.SPA)
.WithAllowedGrants(GrantTypes.Implicit)
.WithAllowedGrants(GrantTypes.Code)
.WithoutClientSecrets()
.WithPkce()
.AllowAccessTokensViaBrowser();
}

View File

@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
Assert.Empty(client.AllowedCorsOrigins);
Assert.False(client.RequireConsent);
Assert.Empty(client.ClientSecrets);
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
Assert.Equal(GrantTypes.Code.ToArray(), client.AllowedGrantTypes.ToArray());
}
[Fact]
@ -139,7 +139,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
Assert.Equal(new[] { expectedAllowedOrigins }, client.AllowedCorsOrigins);
Assert.False(client.RequireConsent);
Assert.Empty(client.ClientSecrets);
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
Assert.Equal(GrantTypes.Code.ToArray(), client.AllowedGrantTypes.ToArray());
}
[Fact]
@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
Assert.Empty(client.AllowedCorsOrigins);
Assert.False(client.RequireConsent);
Assert.Empty(client.ClientSecrets);
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
Assert.Equal(GrantTypes.Code.ToArray(), client.AllowedGrantTypes.ToArray());
}
}
}

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Extensions
["client_id"] = "SPA",
["redirect_uri"] = "http://localhost/authentication/login-callback",
["post_logout_redirect_uri"] = "http://localhost/authentication/logout-callback",
["response_type"] = "id_token token",
["response_type"] = "code",
["scope"] = "a/b c/d"
};

View File

@ -1,63 +0,0 @@
// 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 System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
public class ClientParametersTagHelperTests
{
[Fact]
public void ProcessThrows_WhenClientIdNotFound()
{
// Arrange
var clientRequestParametersProvider = new Mock<IClientRequestParametersProvider>();
clientRequestParametersProvider.Setup(c => c.GetClientParameters(It.IsAny<HttpContext>(), It.IsAny<string>())).Returns<IDictionary<string, string>>(null);
var tagHelperContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), "id");
var tagHelperOutput = new TagHelperOutput("meta", new TagHelperAttributeList(), (something, encoder) => Task.FromResult<TagHelperContent>(null));
var tagHelper = new ClientParametersTagHelper(clientRequestParametersProvider.Object);
tagHelper.ClientId = "id";
tagHelper.ViewContext = new ViewContext() { HttpContext = new DefaultHttpContext() };
// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(() => tagHelper.Process(tagHelperContext, tagHelperOutput));
Assert.Equal("Parameters for client 'id' not found.", exception.Message);
}
[Fact]
public void ProcessAddsAttributesToTag_WhenClientIdFound()
{
// Arrange
var clientRequestParametersProvider = new Mock<IClientRequestParametersProvider>();
clientRequestParametersProvider.Setup(c => c.GetClientParameters(It.IsAny<HttpContext>(), It.IsAny<string>()))
.Returns(new Dictionary<string, string>()
{
["client_id"] = "SampleApp",
["scope"] = "SampleAPI openid",
["redirect_uri"] = "https://www.example.com/auth-callback",
["response_type"] = "id_token code"
});
var tagHelperContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), "id");
var tagHelperOutput = new TagHelperOutput("meta", new TagHelperAttributeList(), (something, encoder) => Task.FromResult<TagHelperContent>(null));
var tagHelper = new ClientParametersTagHelper(clientRequestParametersProvider.Object);
tagHelper.ViewContext = new ViewContext() { HttpContext = new DefaultHttpContext() };
// Act
tagHelper.Process(tagHelperContext, tagHelperOutput);
// Assert
Assert.Contains(tagHelperOutput.Attributes, th => th.Name == "data-client_id" && th.Value is string value && value == "SampleApp");
Assert.Contains(tagHelperOutput.Attributes, th => th.Name == "data-scope" && th.Value is string value && value == "SampleAPI openid");
Assert.Contains(tagHelperOutput.Attributes, th => th.Name == "data-redirect_uri" && th.Value is string value && value == "https://www.example.com/auth-callback");
Assert.Contains(tagHelperOutput.Attributes, th => th.Name == "data-response_type" && th.Value is string value && value == "id_token code");
}
}
}

View File

@ -21,4 +21,4 @@ else
<li><a asp-area="Identity" asp-page="/Account/Register">Register</a></li>
<li><a asp-area="Identity" asp-page="/Account/Login">Login</a></li>
</ul>
}
}

View File

@ -0,0 +1,12 @@
{
"solution": {
"path": "ProjectTemplates.sln",
"projects": [
"Web.Client.ItemTemplates\\Microsoft.DotNet.Web.Client.ItemTemplates.csproj",
"Web.ItemTemplates\\Microsoft.DotNet.Web.ItemTemplates.csproj",
"Web.ProjectTemplates\\Microsoft.DotNet.Web.ProjectTemplates.csproj",
"Web.Spa.ProjectTemplates\\Microsoft.DotNet.Web.Spa.ProjectTemplates.csproj",
"test\\ProjectTemplates.Tests.csproj"
]
}
}

View File

@ -92,7 +92,6 @@
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -105,16 +104,12 @@
"nan": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
"dev": true,
"optional": true
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
},
"node-sass": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
"integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
"dev": true,
"optional": true,
"requires": {
"async-foreach": "^0.1.3",
"chalk": "^1.1.1",
@ -135,6 +130,15 @@
"true-case-path": "^1.0.2"
}
},
"open": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/open/-/open-6.2.0.tgz",
"integrity": "sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw==",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
}
},
"rxjs": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@ -153,8 +157,7 @@
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
},
"source-map-support": {
"version": "0.5.12",
@ -215,40 +218,28 @@
},
"dependencies": {
"@angular-devkit/architect": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.9.tgz",
"integrity": "sha512-EAFtCs9dsGhpMRC45PoYsrkiExpWz9Ax15qXfzwdDRacz5DmdOVt+QpkLW1beUOwiyj/bhFyj23eaONK2RTn/w==",
"version": "0.800.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.800.6.tgz",
"integrity": "sha512-946ceRci/1yx09g8iRvULLoVihcB2RW9nhpCCMum4L9wheip8t4FWso3pd3JtPQGJV9dmsnwPzR9s12bncmj3g==",
"dev": true,
"requires": {
"@angular-devkit/core": "7.3.9",
"rxjs": "6.3.3"
"@angular-devkit/core": "8.0.6",
"rxjs": "6.4.0"
}
},
"@angular-devkit/core": {
"version": "7.3.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.9.tgz",
"integrity": "sha512-SaxD+nKFW3iCBKsxNR7+66J30EexW/y7tm8m5AvUH+GwSAgIj0ZYmRUzFEPggcaLVA4WnE/YWqIXZMJW5dT7gw==",
"version": "8.0.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.6.tgz",
"integrity": "sha512-gbKEVsQuYqBJPzgaxEitvs0aN9NwmUHhTkum28mRyPbS3witay/q8+3ls48M2W+98Da/PQbfndxFY4OCa+qHEA==",
"dev": true,
"requires": {
"ajv": "6.9.1",
"chokidar": "2.0.4",
"ajv": "6.10.0",
"fast-json-stable-stringify": "2.0.0",
"rxjs": "6.3.3",
"magic-string": "0.25.2",
"rxjs": "6.4.0",
"source-map": "0.7.3"
}
},
"ajv": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
"integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"rxjs": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@ -359,6 +350,15 @@
"ms": "^2.1.1"
}
},
"open": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/open/-/open-6.2.0.tgz",
"integrity": "sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw==",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
}
},
"semver": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz",
@ -383,22 +383,6 @@
"tslib": "^1.9.0"
}
},
"@angular/common": {
"version": "7.2.15",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.15.tgz",
"integrity": "sha512-2b5JY2HWVHCf3D1GZjmde7jdAXSTXkYtmjLtA9tQkjOOTr80eHpNSujQqnzb97dk9VT9OjfjqTQd7K3pxZz8jw==",
"requires": {
"tslib": "^1.9.0"
}
},
"@angular/compiler": {
"version": "7.2.15",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.15.tgz",
"integrity": "sha512-5yb4NcLk8GuXkYf7Dcor4XkGueYp4dgihzDmMjYDUrV0NPhubKlr+SwGtLOtzgRBWJ1I2bO0S3zwa0q0OgIPOw==",
"requires": {
"tslib": "^1.9.0"
}
},
"@angular/compiler-cli": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.0.0.tgz",
@ -657,33 +641,6 @@
"@babel/highlight": "^7.0.0"
}
},
"@babel/generator": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz",
"integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==",
"dev": true,
"requires": {
"@babel/types": "^7.4.4",
"jsesc": "^2.5.1",
"lodash": "^4.17.11",
"source-map": "^0.5.0",
"trim-right": "^1.0.1"
},
"dependencies": {
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
"dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
}
}
},
"@babel/helper-function-name": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
@ -704,15 +661,6 @@
"@babel/types": "^7.0.0"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
"integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
"dev": true,
"requires": {
"@babel/types": "^7.4.4"
}
},
"@babel/highlight": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
@ -778,40 +726,6 @@
"@babel/types": "^7.4.4"
}
},
"@babel/traverse": {
"version": "7.4.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz",
"integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/generator": "^7.4.4",
"@babel/helper-function-name": "^7.1.0",
"@babel/helper-split-export-declaration": "^7.4.4",
"@babel/parser": "^7.4.5",
"@babel/types": "^7.4.4",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.11"
},
"dependencies": {
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
}
}
},
"@babel/types": {
"version": "7.4.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz",
@ -845,30 +759,18 @@
},
"dependencies": {
"@angular-devkit/core": {
"version": "7.3.9",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.9.tgz",
"integrity": "sha512-SaxD+nKFW3iCBKsxNR7+66J30EexW/y7tm8m5AvUH+GwSAgIj0ZYmRUzFEPggcaLVA4WnE/YWqIXZMJW5dT7gw==",
"version": "8.0.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.0.6.tgz",
"integrity": "sha512-gbKEVsQuYqBJPzgaxEitvs0aN9NwmUHhTkum28mRyPbS3witay/q8+3ls48M2W+98Da/PQbfndxFY4OCa+qHEA==",
"dev": true,
"requires": {
"ajv": "6.9.1",
"chokidar": "2.0.4",
"ajv": "6.10.0",
"fast-json-stable-stringify": "2.0.0",
"rxjs": "6.3.3",
"magic-string": "0.25.2",
"rxjs": "6.4.0",
"source-map": "0.7.3"
}
},
"ajv": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
"integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"rxjs": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
@ -1222,8 +1124,7 @@
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
"optional": true
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"accepts": {
"version": "1.3.7",
@ -1421,8 +1322,7 @@
"array-find-index": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
"optional": true
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
},
"array-flatten": {
"version": "2.1.2",
@ -1556,8 +1456,7 @@
"async-foreach": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
"integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
"optional": true
"integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
},
"async-limiter": {
"version": "1.0.0",
@ -1856,7 +1755,6 @@
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"optional": true,
"requires": {
"inherits": "~2.0.0"
}
@ -2252,14 +2150,12 @@
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
"optional": true
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
},
"camelcase-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"optional": true,
"requires": {
"camelcase": "^2.0.0",
"map-obj": "^1.0.0"
@ -2410,7 +2306,6 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"optional": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
@ -2686,12 +2581,6 @@
"safe-buffer": "~5.1.1"
}
},
"cookie": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
"dev": true
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@ -2834,7 +2723,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
"integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
"optional": true,
"requires": {
"lru-cache": "^4.0.1",
"which": "^1.2.9"
@ -2895,7 +2783,6 @@
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
"optional": true,
"requires": {
"array-find-index": "^1.0.1"
}
@ -3730,6 +3617,12 @@
"toidentifier": "1.0.0"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
"dev": true
},
"mime-db": {
"version": "1.40.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
@ -4176,7 +4069,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -4197,12 +4091,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4217,17 +4113,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -4344,7 +4243,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -4356,6 +4256,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -4370,6 +4271,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -4377,12 +4279,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -4401,6 +4305,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -4481,7 +4386,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -4493,6 +4399,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4578,7 +4485,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -4614,6 +4522,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4633,6 +4542,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -4676,12 +4586,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@ -4689,7 +4601,6 @@
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
"optional": true,
"requires": {
"graceful-fs": "^4.1.2",
"inherits": "~2.0.0",
@ -4716,7 +4627,6 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
"integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
"optional": true,
"requires": {
"globule": "^1.0.0"
}
@ -4818,7 +4728,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
"integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
"optional": true,
"requires": {
"glob": "~7.1.1",
"lodash": "~4.17.10",
@ -5165,7 +5074,8 @@
"immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
"optional": true
},
"import-cwd": {
"version": "2.1.0",
@ -5214,14 +5124,12 @@
"in-publish": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
"integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=",
"optional": true
"integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
},
"indent-string": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
"optional": true,
"requires": {
"repeating": "^2.0.0"
}
@ -5381,8 +5289,7 @@
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
"optional": true
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
},
"ip": {
"version": "1.1.5",
@ -5767,7 +5674,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
"integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
"dev": true,
"requires": {
"neo-async": "^2.6.0",
"optimist": "^0.6.1",
@ -5778,8 +5684,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
@ -5804,11 +5709,29 @@
"semver": "^6.0.0"
}
},
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
"dev": true
},
"semver": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
"integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==",
"dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
"dev": true
}
}
},
@ -6010,8 +5933,7 @@
"js-base64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
"optional": true
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw=="
},
"js-tokens": {
"version": "3.0.2",
@ -6248,7 +6170,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"optional": true,
"requires": {
"invert-kv": "^1.0.0"
}
@ -6312,6 +6233,7 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"optional": true,
"requires": {
"immediate": "~3.0.5"
}
@ -6364,9 +6286,9 @@
}
},
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"lodash.clonedeep": {
"version": "4.5.0",
@ -6423,7 +6345,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
"optional": true,
"requires": {
"currently-unhandled": "^0.4.1",
"signal-exit": "^3.0.0"
@ -6592,7 +6513,6 @@
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
"optional": true,
"requires": {
"camelcase-keys": "^2.0.0",
"decamelize": "^1.1.2",
@ -6668,12 +6588,6 @@
"mime-db": "1.40.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
"mini-css-extract-plugin": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz",
@ -6885,8 +6799,7 @@
"neo-async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
"dev": true
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="
},
"nice-try": {
"version": "1.0.5",
@ -6924,7 +6837,6 @@
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
"optional": true,
"requires": {
"fstream": "^1.0.0",
"glob": "^7.0.3",
@ -6943,8 +6855,7 @@
"semver": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"optional": true
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
}
}
},
@ -7025,7 +6936,6 @@
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
"optional": true,
"requires": {
"abbrev": "1"
}
@ -7243,9 +7153,9 @@
"dev": true
},
"oidc-client": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.8.2.tgz",
"integrity": "sha512-WwoSY8S6QyNN3qpne88YurjNqjTf6z1Xr0y+OrFVvdnVPYcefkTtXlZ5iOwR2JrmP4vBuq2j8eTjUJyDZFrFNQ==",
"version": "1.9.0-beta.1",
"resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.9.0-beta.1.tgz",
"integrity": "sha512-K+j4RxVw2Tjf8UiUL4XRLIvA77TQrZqZFCM2I//KeopWVapTfzGhdmc39qAATpO0SRYc75LLvx4DsrzG/Zu6qw==",
"requires": {
"uuid": "^3.3.2"
}
@ -7290,24 +7200,6 @@
}
}
},
"open": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/open/-/open-6.2.0.tgz",
"integrity": "sha512-Vxf6HJkwrqmvh9UAID3MnMYXntbTxKLOSfOnO7LJdzPf3NE3KQYFNV0/Lcz2VAndbRFil58XVCyh8tiX11fiYw==",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
}
},
"open": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/open/-/open-6.0.0.tgz",
"integrity": "sha512-/yb5mVZBz7mHLySMiSj2DcLtMBbFPJk5JBKEkHVZFxZAPzeg3L026O0T+lbdz1B2nyDnkClRSwRQJdeVUIF7zw==",
"dev": true,
"requires": {
"is-wsl": "^1.1.0"
}
},
"opn": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
@ -7357,7 +7249,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"optional": true,
"requires": {
"lcid": "^1.0.0"
}
@ -7525,7 +7416,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"optional": true,
"requires": {
"error-ex": "^1.2.0"
}
@ -8000,7 +7890,8 @@
"q": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4="
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
"optional": true
},
"qjobs": {
"version": "1.2.0",
@ -8201,7 +8092,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
"optional": true,
"requires": {
"indent-string": "^2.1.0",
"strip-indent": "^1.0.1"
@ -8471,7 +8361,6 @@
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
"integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
"optional": true,
"requires": {
"glob": "^7.0.0",
"lodash": "^4.0.0",
@ -8513,7 +8402,8 @@
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"optional": true
},
"schema-utils": {
"version": "1.0.0",
@ -8530,7 +8420,6 @@
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
"integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
"optional": true,
"requires": {
"js-base64": "^2.1.8",
"source-map": "^0.4.2"
@ -8546,6 +8435,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
"integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
"optional": true,
"requires": {
"jszip": "^3.1.3",
"rimraf": "^2.5.4",
@ -8713,7 +8603,8 @@
"set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"optional": true
},
"set-value": {
"version": "2.0.1",
@ -9420,7 +9311,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
"integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
"optional": true,
"requires": {
"readable-stream": "^2.0.1"
}
@ -9527,7 +9417,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
"optional": true,
"requires": {
"get-stdin": "^4.0.1"
}
@ -9619,7 +9508,6 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
"optional": true,
"requires": {
"block-stream": "*",
"fstream": "^1.0.12",
@ -9809,8 +9697,7 @@
"trim-newlines": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
"optional": true
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
},
"trim-right": {
"version": "1.0.1",
@ -9822,7 +9709,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
"integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
"optional": true,
"requires": {
"glob": "^7.1.2"
}
@ -10000,7 +9886,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
"dev": true,
"optional": true,
"requires": {
"commander": "~2.20.0",
@ -10011,7 +9896,6 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"optional": true
}
}
@ -10705,8 +10589,7 @@
"which-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
"optional": true
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
},
"wide-align": {
"version": "1.1.3",
@ -10773,6 +10656,7 @@
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"optional": true,
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~9.0.1"
@ -10781,7 +10665,8 @@
"xmlbuilder": {
"version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
"optional": true
},
"xmlhttprequest-ssl": {
"version": "1.5.5",
@ -10809,7 +10694,6 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
"integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
"optional": true,
"requires": {
"camelcase": "^3.0.0",
"cliui": "^3.2.0",
@ -10829,8 +10713,7 @@
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"optional": true
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
}
}
},
@ -10838,7 +10721,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
"integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
"optional": true,
"requires": {
"camelcase": "^3.0.0"
},
@ -10846,8 +10728,7 @@
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
"optional": true
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
}
}
},

View File

@ -22,14 +22,14 @@
"@angular/platform-server": "8.0.0",
"@angular/router": "8.0.0",
"@nguniversal/module-map-ngfactory-loader": "8.0.0-rc.1",
"core-js": "^2.6.5",
"rxjs": "^6.4.0",
"zone.js": "~0.9.1",
"aspnet-prerendering": "^3.0.1",
"bootstrap": "^4.3.1",
"core-js": "^2.6.5",
"jquery": "3.4.1",
"oidc-client": "^1.8.0",
"popper.js": "^1.14.3"
"oidc-client": "^1.9.0-beta.1",
"popper.js": "^1.14.3",
"rxjs": "^6.4.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.800.6",

View File

@ -130,56 +130,27 @@ export class AuthorizeService {
// the response and redirect to the return url or display an error message.
public async completeSignIn(url: string): Promise<IAuthenticationResult> {
await this.ensureUserManagerInitialized();
let response;
try {
response = await this.getSignInResponse(url);
if (!!response.error) {
return this.error(`${response.error}: ${response.error_description}`);
}
} catch (processSignInResponseError) {
if (processSignInResponseError.error === 'login_required') {
// This error is thrown by the underlying oidc client when it tries to log in
// the user silently as in case 1 defined above and the IdP requires the user
// to enter credentials. We let the user manager handle the response to notify
// the main window.
response = processSignInResponseError;
} else {
console.log('There was an error processing the sign-in response: ', processSignInResponseError);
return this.error('There was an error processing the sign-in response.');
}
}
const { state } = await (this.userManager as any).readSigninResponseState(url, this.userManager.settings.stateStore);
if (state.request_type === 'si:r' || !state.request_type) {
const user = await this.userManager.signinRedirectCallback(url);
this.userSubject.next(user.profile);
return this.success(state.data.userState);
const authenticationState = response.state as IAuthenticationState;
const mode = authenticationState.mode;
}
if (state.request_type === 'si:p') {
await this.userManager.signinPopupCallback(url);
return this.success(undefined);
}
if (state.request_type === 'si:s') {
await this.userManager.signinSilentCallback(url);
return this.success(undefined);
}
switch (mode) {
case LoginMode.Silent:
try {
await this.userManager.signinSilentCallback(url);
return this.success(undefined);
} catch (silentCallbackError) {
console.log('Silent callback authentication error: ', silentCallbackError);
return this.error('Silent callback authentication error');
}
case LoginMode.PopUp:
try {
await this.userManager.signinPopupCallback(url);
return this.success(undefined);
} catch (popupCallbackError) {
console.log('Popup callback authentication error: ', popupCallbackError);
return this.error('Popup callback authentication error.');
}
case LoginMode.Redirect:
try {
const user = await this.userManager.signinRedirectCallback(url);
this.userSubject.next(user.profile);
return this.success(response.state.userState);
} catch (redirectCallbackError) {
console.log('Redirect callback authentication error: ', redirectCallbackError);
return this.error('Redirect callback authentication error.');
}
default:
throw new Error(`Invalid login mode '${mode}'.`);
throw new Error(`Invalid login mode '${state.request_type}'.`);
} catch (signInResponseError) {
console.log('There was an error signing in', signInResponseError);
return this.error('Sing in callback authentication error.');
}
}
@ -214,74 +185,23 @@ export class AuthorizeService {
// the response and redirect to the logged-out url or display an error message.
public async completeSignOut(url: string): Promise<IAuthenticationResult> {
await this.ensureUserManagerInitialized();
let response;
try {
response = await await this.getSignOutResponse(url);
} catch (processSignOutResponseError) {
console.log('There was an error processing the sign-out response: ', processSignOutResponseError);
response = processSignOutResponseError;
}
if (!!response.error) {
return this.error(`${response.error}: ${response.error_description}`);
}
const authenticationState = response.state as IAuthenticationState;
const mode = (authenticationState && authenticationState.mode) ||
!!window.opener ? LoginMode.PopUp : LoginMode.Redirect;
switch (mode) {
case LoginMode.PopUp:
try {
await this.userManager.signoutPopupCallback(url);
return this.success(response.state && response.state.userState);
} catch (popupCallbackError) {
console.log('Popup signout callback error: ', popupCallbackError);
return this.error('Popup signout callback error');
}
case LoginMode.Redirect:
try {
const { state } = await (this.userManager as any).readSignoutResponseState(url, this.userManager.settings.stateStore);
if (state) {
if (state.request_type === 'so:r') {
await this.userManager.signoutRedirectCallback(url);
this.userSubject.next(null);
return this.success(response.state.userState);
} catch (redirectCallbackError) {
console.log('Redirect signout callback error: ', redirectCallbackError);
return this.error('Redirect signout callback error');
return this.success(state.data.userState);
}
default:
throw new Error(`Invalid LoginMode '${mode}'.`);
}
}
private async getSignInResponse(url: string) {
const keys = await this.userManager.settings.stateStore.getAllKeys();
const states = keys.map(key => ({ key, state: this.userManager.settings.stateStore.get(key) }));
for (const state of states) {
state.state = await state.state;
}
try {
const response = await this.userManager.processSigninResponse(url);
return response;
} finally {
for (const state of states) {
await this.userManager.settings.stateStore.set(state.key, state.state);
}
}
}
private async getSignOutResponse(url: string) {
const keys = await this.userManager.settings.stateStore.getAllKeys();
const states = keys.map(key => ({ key, state: this.userManager.settings.stateStore.get(key) }));
for (const state of states) {
state.state = await state.state;
}
try {
const response = await this.userManager.processSignoutResponse(url);
return response;
} finally {
for (const state of states) {
await this.userManager.settings.stateStore.set(state.key, state.state);
if (state.request_type === 'so:p') {
await this.userManager.signoutPopupCallback(url);
return this.success(state.data && state.data.userState);
}
throw new Error(`Invalid login mode '${state.request_type}'.`);
}
} catch (signInResponseError) {
console.log('There was an error signing out', signInResponseError);
return this.error('Sign out callback authentication error.');
}
}
@ -318,9 +238,6 @@ export class AuthorizeService {
const settings: any = await response.json();
settings.automaticSilentRenew = true;
settings.includeIdTokenInSilentRenew = true;
settings.userStore = new WebStorageStateStore({
prefix: ApplicationName
});
this.userManager = new UserManager(settings);
this.userManager.events.addUserSignedOut(async () => {

View File

@ -3,6 +3,15 @@
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@{
string returnUrl = null;
var query = ViewContext.HttpContext.Request.Query;
if (query.ContainsKey("returnUrl"))
{
returnUrl = query["returnUrl"];
}
}
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
@ -18,10 +27,10 @@
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register" asp-route-returnUrl="@returnUrl">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login" asp-route-returnUrl="@returnUrl">Login</a>
</li>
}
</ul>

View File

@ -6696,7 +6696,8 @@
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
"bundled": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -6733,7 +6734,8 @@
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
@ -6742,7 +6744,8 @@
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
"bundled": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -6845,7 +6848,8 @@
},
"inherits": {
"version": "2.0.3",
"bundled": true
"bundled": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -6855,6 +6859,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -6874,11 +6879,13 @@
},
"minimist": {
"version": "0.0.8",
"bundled": true
"bundled": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -6895,6 +6902,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -6967,7 +6975,8 @@
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -6977,6 +6986,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -7052,7 +7062,8 @@
},
"safe-buffer": {
"version": "5.1.2",
"bundled": true
"bundled": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -7082,6 +7093,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -7099,6 +7111,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -7137,11 +7150,13 @@
},
"wrappy": {
"version": "1.0.2",
"bundled": true
"bundled": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true
"bundled": true,
"optional": true
}
}
}
@ -7791,9 +7806,9 @@
}
},
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"lodash._reinterpolate": {
"version": "3.0.0",
@ -8137,9 +8152,9 @@
}
},
"mixin-deep": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
"integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
"requires": {
"for-in": "^1.0.2",
"is-extendable": "^1.0.1"
@ -8539,9 +8554,9 @@
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
},
"oidc-client": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.8.0.tgz",
"integrity": "sha512-RHGE3UU+NgFHUj4XxqOi+fgu/KGEpBoypXRXMVXlW3d/pU3M/Tw3L+K/PyOcyCsTWtS+KngD/9tPqsEcWt5eMg==",
"version": "1.9.0-beta.1",
"resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.9.0-beta.1.tgz",
"integrity": "sha512-K+j4RxVw2Tjf8UiUL4XRLIvA77TQrZqZFCM2I//KeopWVapTfzGhdmc39qAATpO0SRYc75LLvx4DsrzG/Zu6qw==",
"requires": {
"uuid": "^3.3.2"
}
@ -11019,9 +11034,9 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"set-value": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
"integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
"requires": {
"extend-shallow": "^2.0.1",
"is-extendable": "^0.1.1",
@ -12026,35 +12041,14 @@
}
},
"union-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
"integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
"requires": {
"arr-union": "^3.1.0",
"get-value": "^2.0.6",
"is-extendable": "^0.1.1",
"set-value": "^0.4.3"
},
"dependencies": {
"extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
"requires": {
"is-extendable": "^0.1.0"
}
},
"set-value": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
"integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
"requires": {
"extend-shallow": "^2.0.1",
"is-extendable": "^0.1.1",
"is-plain-object": "^2.0.1",
"to-object-path": "^0.3.0"
}
}
"set-value": "^2.0.1"
}
},
"uniq": {

View File

@ -3,11 +3,11 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"bootstrap": "^4.1.3",
"babel-eslint": "10.0.1",
"bootstrap": "^4.1.3",
"jquery": "^3.4.1",
"merge": "^1.2.1",
"oidc-client": "^1.8.0",
"oidc-client": "^1.9.0-beta.1",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-router-bootstrap": "^0.24.4",

View File

@ -88,56 +88,26 @@ export class AuthorizeService {
// the response and redirect to the return url or display an error message.
async completeSignIn(url) {
await this.ensureUserManagerInitialized();
let response = undefined;
try {
response = await this.getSignInResponse(url);
if (!!response.error) {
return this.error(`${response.error}: ${response.error_description}`);
const { state } = await this.userManager.readSigninResponseState(url, this.userManager.settings.stateStore);
if (state.request_type === 'si:r' || !state.request_type) {
let user = await this.userManager.signinRedirectCallback(url);
this.updateState(user);
return this.success(state.data.userState);
}
} catch (processSignInResponseError) {
if (processSignInResponseError.error === "login_required") {
// This error is thrown by the underlying oidc client when it tries to log in
// the user silently as in case 1 defined above and the IdP requires the user
// to enter credentials. We let the user manager handle the response to notify
// the main window.
response = processSignInResponseError;
} else {
console.log("There was an error processing the sign-in response: ", processSignInResponseError);
return this.error("There was an error processing the sign-in response.");
if (state.request_type === 'si:p') {
await this.userManager.signinSilentCallback(url);
return this.success(undefined);
}
if (state.request_type === 'si:s') {
await this.userManager.signinSilentCallback(url);
return this.success(undefined);
}
}
const authenticationState = response.state;
const mode = authenticationState.mode;
switch (mode) {
case LoginMode.Silent:
try {
await this.userManager.signinSilentCallback(url);
return this.success(undefined);
} catch (silentCallbackError) {
console.log("Silent callback authentication error: ", silentCallbackError);
return this.error("Silent callback authentication error");
}
case LoginMode.PopUp:
try {
await this.userManager.signinPopupCallback(url);
return this.success(undefined);
} catch (popupCallbackError) {
console.log("Popup callback authentication error: ", popupCallbackError);
return this.error("Popup callback authentication error.");
}
case LoginMode.Redirect:
try {
let user = await this.userManager.signinRedirectCallback(url);
this.updateState(user);
return this.success(response.state.userState);
} catch (redirectCallbackError) {
console.log("Redirect callback authentication error: ", redirectCallbackError);
return this.error("Redirect callback authentication error.");
}
default:
throw new Error(`Invalid login mode '${mode}'.`);
throw new Error(`Invalid login mode '${state.request_type}'.`);
} catch (signInResponseError) {
console.log('There was an error signing in', signInResponseError);
return this.error('Sing in callback authentication error.');
}
}
@ -172,42 +142,23 @@ export class AuthorizeService {
// the response and redirect to the logged-out url or display an error message.
async completeSignOut(url) {
await this.ensureUserManagerInitialized();
let response = undefined;
try {
response = await await this.getSignOutResponse(url);
} catch (processSignOutResponseError) {
console.log("There was an error processing the sign-out response: ", processSignOutResponseError);
response = processSignOutResponseError;
}
if (!!response.error) {
return this.error(`${response.error}: ${response.error_description}`);
}
const authenticationState = response.state;
const mode = (authenticationState && authenticationState.mode) ||
!!window.opener ? LoginMode.PopUp : LoginMode.Redirect;
switch (mode) {
case LoginMode.PopUp:
try {
await this.userManager.signoutPopupCallback(url);
return this.success(response.state && response.state.userState);
} catch (popupCallbackError) {
console.log("Popup signout callback error: ", popupCallbackError);
return this.error("Popup signout callback error");
}
case LoginMode.Redirect:
try {
const { state } = await this.userManager.readSignoutResponseState(url, this.userManager.settings.stateStore);
if (state) {
if (state.request_type === 'so:r') {
await this.userManager.signoutRedirectCallback(url);
this.updateState(undefined);
return this.success(response.state.userState);
} catch (redirectCallbackError) {
console.log("Redirect signout callback error: ", redirectCallbackError);
return this.error("Redirect signout callback error");
this.userSubject.next(null);
return this.success(state.data.userState);
}
default:
throw new Error(`Invalid LoginMode '${mode}'.`);
if (state.request_type === 'so:p') {
await this.userManager.signoutPopupCallback(url);
return this.success(state.data && state.data.userState);
}
throw new Error(`Invalid login mode '${state.request_type}'.`);
}
} catch (signInResponseError) {
console.log('There was an error signing out', signInResponseError);
return this.error('Sign out callback authentication error.');
}
}
@ -240,38 +191,6 @@ export class AuthorizeService {
}
}
async getSignInResponse(url) {
const keys = await this.userManager.settings.stateStore.getAllKeys();
const states = keys.map(key => ({ key, state: this.userManager.settings.stateStore.get(key) }));
for (const state of states) {
state.state = await state.state;
}
try {
const response = await this.userManager.processSigninResponse(url);
return response;
} finally {
for (const state of states) {
await this.userManager.settings.stateStore.set(state.key, state.state);
}
}
}
async getSignOutResponse(url) {
const keys = await this.userManager.settings.stateStore.getAllKeys();
const states = keys.map(key => ({ key, state: this.userManager.settings.stateStore.get(key) }));
for (const state of states) {
state.state = await state.state;
}
try {
const response = await this.userManager.processSignoutResponse(url);
return response;
} finally {
for (const state of states) {
await this.userManager.settings.stateStore.set(state.key, state.state);
}
}
}
createArguments(mode, state) {
if (mode !== LoginMode.Silent) {
return { data: { mode, userState: state } };

View File

@ -3,6 +3,15 @@
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
@{
string returnUrl = null;
var query = ViewContext.HttpContext.Request.Query;
if (query.ContainsKey("returnUrl"))
{
returnUrl = query["returnUrl"];
}
}
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
@ -18,10 +27,10 @@
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register" asp-route-returnUrl="@returnUrl">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login"asp-route-returnUrl="@returnUrl">Login</a>
</li>
}
</ul>