parent
2df72072ad
commit
2287abcc3e
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue