如何通过JavaScript与IdentityServer3传递我的访问令牌?

时间:2015-05-29 12:42:16

标签: identityserver3

我有一个带有大量JavaScript调用的Asp.Net MVC应用程序。我已经保护了MVC操作,被重定向到身份服务器,登录,然后被重定向回客户端。我可以通过MVC进行后续调用,但是如何获取该访问令牌并在ajax调用中使用它?

这是我的Startup.cs文件:

public void Configuration(IAppBuilder app)
{
    // Tell Microsoft to not try to map to .Net's ClaimsTypes
    JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = "Cookies"
    });

    const string svcUrl = "https://localhost/svc.security";

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        Authority = svcUrl,
        ClientId = "nedd_client",
        RedirectUri = "http://localhost:61207/",
        ResponseType = "code id_token token",

        // Ask for 'roles' claims & for access to web services
        Scope = "openid profile",

        SignInAsAuthenticationType = "Cookies",

        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthorizationCodeReceived = async n =>
            {
                // filter "protocol" claims
                var claims = new List<Claim>(from c in n.AuthenticationTicket.Identity.Claims
                                             where c.Type != "iss" &&
                                                   c.Type != "aud" &&
                                                   c.Type != "nbf" &&
                                                   c.Type != "exp" &&
                                                   c.Type != "iat" &&
                                                   c.Type != "nonce" &&
                                                   c.Type != "c_hash" &&
                                                   c.Type != "at_hash"
                                             select c);

                // Get userinfo data
                var userInfoClient = new UserInfoClient(new Uri(svcUrl + "/connect/userinfo"), n.ProtocolMessage.AccessToken);

                var userInfo = await userInfoClient.GetAsync();
                userInfo.Claims.ToList().ForEach(ui => claims.Add(new Claim(ui.Item1, ui.Item2)));

                // Get access token
                var tokenClient = new OAuth2Client(new Uri(svcUrl + "/connect/token"), "nedd_client", "secret");

                var response = await tokenClient.RequestAuthorizationCodeAsync(n.Code, n.RedirectUri);

                claims.Add(new Claim("access_token", response.AccessToken));
                claims.Add(new Claim("expires_at", DateTime.Now.AddSeconds(response.ExpiresIn).ToLocalTime().ToString()));
                claims.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                n.AuthenticationTicket = new AuthenticationTicket(new ClaimsIdentity(claims.Distinct(new ClaimComparer()), n.AuthenticationTicket.Identity.AuthenticationType), n.AuthenticationTicket.Properties);
            },
        }

    });

}

以下是ajax调用的示例:

$.ajax({
    type: 'GET',
    url: "https://localhost/svc.security/connect/userinfo",
    //headers: { "Authorization": "Bearer " + my.getAccessToken() },   // get access token from cookie?

}).done(function (data, textStatus, jqXHR) {
    show(JSON.parse(jqXHR.response));       

2 个答案:

答案 0 :(得分:2)

我意识到我的真​​正问题是,登录后,cookie是一个ASP.Net服务器cookie,客户端无法访问。

我向我的MVC控制器添加了一个方法,用于检索服务器已有的令牌。

    [Authorize]
    public ActionResult GetAccessToken()
    {
        var token = (System.Web.HttpContext.Current.User.Identity as ClaimsIdentity).FindFirst("access_token");
        if (token != null)
        {
            return Content(token.Value);
        }

        return Content("");
    }

然后我的javascript看起来像这样,在对Web服务进行ajax调用之前调用它来获取令牌。

function getAccessToken() {
    var returnVal = "";

    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://localhost:61207/Home/GetAccessToken", false);
    xhr.send();
    returnVal = xhr.responseText;

    return returnVal;
}

可能有一个更优雅的不同解决方案,但是一旦我清楚地知道客户端和服务器上可用的内容,这似乎是最好的解决方案。

答案 1 :(得分:1)

我认为在登录成功之后,你应该将令牌保留在某个位置(例如在cookie中),然后你的“my.getAccessToken()”应该从那里读取。

此示例执行类似的https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/JavaScriptImplicitClient/index.html

 if (window.location.hash) {
        handleCallback();
    }