2014-11-04 58 views
4

我已經經歷了大量Google文檔和SO Q/A,但沒有運氣。我想知道是否有人已經按照Google的建議成功地使用了OpenId到OpenId Connect的遷移。Google OpenId Connect遷移:在ASP.NET應用程序中獲取openid_id

這是我們用來做:

IAuthenticationResponse response = _openid.GetResponse(); 
if (response != null) { 
    //omitted for brevity  
} else { 
    IAuthenticationRequest req = _openid.CreateRequest("https://www.google.com/accounts/o8/id"); 
    req.AddExtension(new ClaimsRequest 
        { 
         Country = DemandLevel.Request, 
         Email = DemandLevel.Request, 
         Gender = DemandLevel.Require, 
         PostalCode = DemandLevel.Require, 
         TimeZone = DemandLevel.Require 
        }); 
    req.RedirectToProvider(); 
} 

這是使用版本DotNetOpenAuth的可以追溯到幾年完成。由於Google不贊成使用OpenId身份驗證,因此我們正在嘗試轉移到OpenID Connect。這裏的關鍵問題是:我能否以某種方式使用最新版本的DotNetOpenAuth庫或其他任何方式獲得OpenId標識符(形式爲https://www.google.com/accounts/o8/id?id=xyz)?

我試過最新的DotNetOpenAuth,我可以讓它工作,但它給了我一個新的Id(這是預期的)。我也用這個URL嘗試JavaScript的方式(換行符爲了可讀性):

https://accounts.google.com/o/oauth2/auth? 
    scope=openid%20profile%20email 
    &openid.realm=http://localhost/palkkac/ 
    &client_id=//here is the client id I created in google developer console 
    &redirect_uri=http://localhost/palkkac/someaspxpagehere 
    &response_type=id_token%20token 

我檢查(使用招),我們使用舊DotNetOpenAuth代碼發送當前的境界值,它是http://localhost/palkkac/。我已經在上面的url中放置了相同的領域。重定向網址與域值開始,但它不完全相同。

當我重定向到一個簡單的頁面解析id_token和密碼進行解密(使用https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=zyx終點)我得到這樣的:

audience "client id is here" 
email "[email protected]" 
expires_in 3597 
issued_at //some numbers here 
issued_to "client id is here" 
issuer "accounts.google.com" 
user_id  "here is a sequence of numbers, my id in the OpenID Connect format that is" 
verified_email true 

因此,有沒有,你會期望找到openid_id領域的標誌在這裏,儘管該消息的整個結構似乎與Google文檔不同,但例如,沒有標題爲sub的字段。我想知道我是否真的在使用錯誤的端點,參數或其他東西?

我一直在閱讀的是移植指南:https://developers.google.com/accounts/docs/OpenID。我跳過了第2步,因爲它看起來像是一個可選步驟。在第3步中,討論了openid_id字段,我想首先將其作爲概念證明。

我們在Google上註冊了應用程序,以創建客戶端ID等。現在還有許多允許的重定向網址以及在Google開發控制檯中列出的JavaScript來源。讓我知道如果這些可能會搞砸這個系統,我會在這裏張貼他們的評論。

注意:我們應該將應用程序移動到嚴格防火牆的環境中,在那裏我們需要打開端口才能在服務器端執行此操作。因此,首選客戶端JavaScript解決方案來訪問谷歌並結合HTTPS並將結果重定向到服務器(除非有其他說法與此相反)。

上有SO對此同樣問題的其他資源,儘管所有這些似乎都使用不同的庫在服務器端做的工作,似乎沒有人在使用Javascript作出的任何嘗試:

  • 這裏(https://stackoverflow.com/questions/22842475/migrating-google-openid-to-openid-connect-openid-id-does-not-match)我認爲通過將領域設置爲與舊的OpenId2.0流程相同,解決了問題。這似乎不適用於我的情況。
  • over here openid_id字段也不存在,但這裏的問題更多地是關於如何使用DotNetOpenAuth以外的庫從Google請求id_token。
  • here似乎有類似的問題讓谷歌返回openid_id字段。
+0

幫助我們也一直無法經過一個多月的搜索後找到解決這個問題的辦法。 – spadelives 2014-11-05 20:46:55

+0

@spadelives我看到你終於想出瞭如何使用Owin和ASP.NET MVC發送領域參數(參考你的SO問題)。但是你仍然沒有得到兩個身份證,是這樣嗎? – mikkark 2014-11-07 06:17:56

+0

是的,我使用cortex93 – spadelives 2014-11-08 17:42:49

回答

2

您可以使用GoogleAuthentication owin中間件。

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions 
{ 
    SignInAsAuthenticationType = signAs, 
    AuthenticationType = "Google", 
    ClientId = "xxx.apps.googleusercontent.com", 
    ClientSecret = "xx", 
    CallbackPath = PathString.FromUriComponent("/oauth2callback"), 
    Provider = new GoogleOAuth2AuthenticationProvider 
    { 
     OnApplyRedirect = context => 
     { 
      context.Response.Redirect(context.RedirectUri + "&openid.realm=https://mydomain.com/"); // DotNetOpenAuth by default add a trailing slash, it must be exactly the same as before 
     } 
    }, 
    BackchannelHttpHandler = new MyWebRequestHandler() 
} 

然後,添加一個新的類名爲MyWebRequestHandler:

public class MyWebRequestHandler : WebRequestHandler 
    { 
     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 
      var httpResponse = await base.SendAsync(request, cancellationToken); 
      if (request.RequestUri == new Uri("https://www.googleapis.com/plus/v1/people/me")) return httpResponse; 

      var configuration = await OpenIdConnectConfigurationRetriever.GetAsync("https://accounts.google.com/.well-known/openid-configuration", cancellationToken); // read the configuration to get the signing tokens (todo should be cached or hard coded) 

      // google is unclear as the openid_id is not in the access_token but in the id_token 
      // as the middleware dot not expose the id_token we need to parse it again 
      var jwt = httpResponse.Content.ReadAsStringAsync().Result; 
      JObject response = JObject.Parse(jwt); 
      string idToken = response.Value<string>((object)"id_token"); 

      JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); 

      try 
      { 
       SecurityToken token; 
       var claims = tokenHandler.ValidateToken(idToken, new TokenValidationParameters() 
       { 
        ValidAudience = "xxx.apps.googleusercontent.com", 
        ValidIssuer = "accounts.google.com", 
        IssuerSigningTokens = configuration.SigningTokens 
       }, out token); 

       var claim = claims.FindFirst("openid_id"); 
       // claim.Value will contain the old openid identifier 
       if (claim != null) Debug.WriteLine(claim.Value); 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine(ex.ToString()); 
      } 
      return httpResponse; 
     } 
    } 

如果你像我一樣發現這不是真的簡單,請upvoting這個問題https://katanaproject.codeplex.com/workitem/359

+0

發佈的端點如果我不完全錯誤,這個答案是ASP.NET MVC特定的?我們的應用程序是普通的ASP.NET,儘管仍然需要應用相同的總體思路。 – mikkark 2014-11-25 14:07:56

+0

好的,這樣的代碼不是特定於MVC。我對OWIN不是很熟悉,所以我弄錯了。我可以確認,我確實可以使用皮層代碼獲得舊ID。現在我想知道如何讓這個Owin代碼在ASP.NET(非MVC)上工作,並且與我們當前的認證機制一起「在一邊」。另外,我們的應用程序是.net 4.0,所以使用Owin需要進行框架升級。 – mikkark 2014-11-27 13:07:58

+0

我設法讓它在純ASP.NET中也能正常工作。我們使用基於SAML的第三方身份驗證庫,這看起來有點讓人頭疼。我刪除它後,我得到了這個工作。實際上,這可能會起作用,因爲我們在不同的服務器上安裝了兩個安裝程序,其中一個正在使用SAML,另一個將使用OAuth而不使用SAML。不過,我想讓他們一起工作,至少要了解他們現在不工作。 – mikkark 2014-11-28 15:23:58

相關問題