如何从JavaScript请求IdentityServer3客户端访问令牌?

时间:2017-03-28 19:53:00

标签: javascript authentication identityserver3 oidc

我有一个基于IdentityServer3的身份验证服务和一个使用IdentityServer Bearer Token身份验证保护的WebAPI Shopper服务。我已经构建了一个简单的MVC客户端应用程序,它可以作为具有访问令牌的客户端应用程序或代表具有身份令牌的经过身份验证的用户访问Shopper服务。 Shopper服务将向经过身份验证的用户返回更多数据。 现在,我正在尝试构建一个JavaScript客户端,该客户端对Shopper服务具有相同的两层访问级别。到目前为止,遵循一些IdentityServer3 JavaScript客户端示例,我已经让JS客户端代表经过身份验证的用户成功调用了Shopper服务。 (我可能需要稍微重新组织代码以适应未经过身份验证的方案,但这不应该太困难。)我不知道如何处理JavaScript代码是请求来自身份验证服务的客户端访问令牌,即MVC客户端中服务器端TokenClient.RequestClientCredentialsAsync(" shopper-service")的JavaScript等价物。有谁知道如何从JavaScript请求该令牌或知道如何做到这一点的示例?这是我到目前为止已经过验证的案例的JavaScript代码,下面是工作的MVC客户端代码:

function display(selector, data) {
    if (data && typeof data === 'string') {
        data = JSON.parse(data);
    }
    if (data) {
        data = JSON.stringify(data, null, 2);
    }

    $(selector).text(data);
}

var settings = {
    authority: 'https://localhost:44332',
    client_id: 'js-sample',
    popup_redirect_uri: 'http://localhost:15264/popup.html',
    response_type: 'id_token token',
    scope: 'openid orvis-shopper-service',
    filterProtocolClaims: false
};

var manager = new Oidc.UserManager(settings);
var user;

manager.events.addUserLoaded(function (loadedUser) {
    user = loadedUser;
    display('.js-user', user);
});

$('.js-login').on('click', function () {
    manager
        .signinPopup()
        .catch(function (error) {
            console.error('error while logging in through the popup', error);
        });
});

$('.js-call-api').on('click', function () {
    var headers = {};
    if (user && user.access_token) {
        headers['Authorization'] = 'Bearer ' + user.access_token;
    }

    $.ajax({
        url: 'https://localhost:44368/api/Shopper/{5FA13934-AD20-4AB2-A386-11653D71AE55}',
        method: 'GET',
        dataType: 'json',
        headers: headers
    }).then(function (data) {
        display('.js-api-result', data);
    }).catch(function (error) {
        display('.js-api-result', {
            status: error.status,
            statusText: error.statusText,
            response: error.responseJSON
        });
    });
});

客户端应用程序代码按照我的意图运行,如下所示:

public async Task<ActionResult> Index()
{
    string tokenValue;
    var user = User as ClaimsPrincipal;
    if (user.Identity.IsAuthenticated)
    {
        tokenValue = user.FindFirst("access_token").Value;
    }
    else
    {
        var tokenResponse = await GetTokenAsync();
        tokenValue = tokenResponse.AccessToken;
    }
    var result = await CallShopperService(tokenValue);
    ViewBag.Json = result;
    return View();
}

private async Task<TokenResponse> GetTokenAsync()
{
    var client = new TokenClient(
        "https://localhost:44332/connect/token",
        "mvc-sample-svc",
        "mvcsamplesecret");

    return await client.RequestClientCredentialsAsync("shopper-service");
}

private async Task<string> CallShopperService(string token)
{
    var client = new HttpClient();
    client.SetBearerToken(token);
    var json = await client.GetStringAsync("https://localhost:44368/api/Shopper/{5FA13934-AD20-4AB2-A386-11653D71AE55}");
    return json;
}

1 个答案:

答案 0 :(得分:0)

JS隐式客户端也可以取回您的访问令牌,只要您根据粘贴的脚本在token中设置response_type

Oidc-client.js构建一个授权质询URL并将浏览器重定向到它,这是登录流程开始的地方。用户登录后,他们会按照相同的重定向路径退回到您的客户端页面。加载客户端页面时(取决于客户端配置的流程,默认情况下应为散列片段),oidc-client从URL(#之后的所有内容)中获取令牌并将其转换为JSON对象,然后保存在本地存储(这意味着你也可以在那里查看)。

我建议使用以下方法来帮助您调试:

  1. 启用流量监控工具(例如fiddler)以确保在登录确实包含访问令牌后您从身份服务器返回的响应(您可以使用https://jwt.io/解码令牌字符串),如果没有,请检查是否授权请求网址正确形成

  2. 如果从身份服务器返回的响应确实包含访问令牌,那么您可以通过在_signinEnd方法

  3. 设置断点来调试oidc-client.js javascript

    希望有所帮助

    已更新,位于评论部分

    对于&#34;匿名令牌&#34;塞纳里奥?如果您正在寻找github.com/IdentityServer/IdentityServer3/issues/1953

    ,请参阅此示例