2015-05-29 98 views
4

我有一個Asp.Net MVC應用程序與大量的JavaScript調用。我保護了MVC操作,重定向到身份服務器,登錄,然後重定向回客戶端。我可以通過MVC進行後續調用,但是如何獲取該訪問令牌並在ajax調用中使用它?如何通過javascript與IdentityServer3傳遞我的訪問令牌?

這是我的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));  
+0

難道你不能只存儲在Web瀏覽器上的本地存儲訪問令牌?訪問令牌不需要保密。如果它被篡改的話,它會被阻止被接受。 – webworm

回答

1

我想登錄成功後,你應該保持令牌一些地方(在餅乾例如),那麼你的「my.getAccessToken()」應該從那裏讀取。

這個例子確實相似https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/JavaScriptImplicitClient/index.html

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

Haz,適用於純JavaScript應用程序,但不適用於混合使用MVC和ajax。我想清楚了,並在下面發佈了我自己的答案。 –

+0

瞭解您的修補程序。它可以工作,但應該提高效率,因爲每次主要請求之前都需要額外的請求。抱歉,由於我的「積分」,我無法評論您的答案;) – hazjack

2

我意識到我真正的問題是事實,在登錄後,該Cookie是一個ASP.Net服務器cookie和客戶端不能訪問。

我添加了一個方法到我的MVC控制器的JavaScript來檢索服務器已經有的令牌。

[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看起來是這樣的,調用它獲取令牌之前,使ajax調用Web服務。

function getAccessToken() { 
    var returnVal = ""; 

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

    return returnVal; 
} 

可能有不同的解決方案,更優雅,但一旦我腦子裏想的是什麼可以在客戶端和服務器清楚,這似乎是最好的解決方案。

相關問題