通過AppAuth iOS理解Google OIDC服務(wù)

通過AppAuth-iOS體驗(yàn)Google OIDC服務(wù)非常容易,只需要配置下面三個(gè)配置項(xiàng)愧沟。

static NSString *const kIssuer = @"https://accounts.google.com";

static NSString *const kClientID = @"24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef.apps.googleusercontent.com";

static NSString *const kRedirectURI = @"com.googleusercontent.apps.24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef:/oauth2redirect/";

通過https://accounts.google.com/.well-known/openid-configuration可以獲取到Google Auth所有的相關(guān)信息,非常豐富的信息。這個(gè)配置文件的詳細(xì)介紹可以參考:OpenID Connect Discovery 1.0 incorporating errata set 1械馆。阿里云和Azure的OIDC Discovery鏈接如下所示。

  1. 阿里云:https://oauth.aliyun.com/.well-known/openid-configuration
  2. Azure:https://login.microsoftonline.com/e86128fb-fc4c-4044-8c6c-98002346bc88/v2.0/.well-known/openid-configuration武通,格式是https://login.microsoftonline.com/{tenantId}/v2.0/.well-known/openid-configuration霹崎,tenantId可以去Azure portal里面的AD里面查看到。

從配置信息可以看出Google把a(bǔ)uth和login放在accounts.google.com域下面冶忱,token單獨(dú)放在www.googleapis.com域下面尾菇。

Paste_Image.png

接下來看看如何發(fā)起授權(quán)。構(gòu)造OIDAuthorizationRequest請(qǐng)求之后囚枪,使用In-App browser(iOS使用SFSafariViewController)打開相應(yīng)的URL派诬。

// builds authentication request
OIDAuthorizationRequest *request =
  [[OIDAuthorizationRequest alloc] initWithConfiguration:configuration
                                                clientId:clientID
                                            clientSecret:clientSecret
                                                  scopes:@[ OIDScopeOpenID, OIDScopeProfile ]
                                             redirectURL:redirectURI
                                            responseType:OIDResponseTypeCode
                                    additionalParameters:nil];
// performs authentication request
AppDelegate *appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[self logMessage:@"Initiating authorization request %@", request];
appDelegate.currentAuthorizationFlow =
  [OIDAuthorizationService presentAuthorizationRequest:request
      presentingViewController:self
                      callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse,
                                 NSError *_Nullable error) {
    if (authorizationResponse) {
      OIDAuthState *authState =
          [[OIDAuthState alloc] initWithAuthorizationResponse:authorizationResponse];
      [self setAuthState:authState];

      [self logMessage:@"Authorization response with code: %@",
                       authorizationResponse.authorizationCode];
      // could just call [self tokenExchange:nil] directly, but will let the user initiate it.
    } else {
      [self logMessage:@"Authorization error: %@", [error localizedDescription]];
    }
  }];

- (SFSafariViewController *)safariViewControllerWithURL:(NSURL *)URL {
  SFSafariViewController *safariViewController =
      [[SFSafariViewController alloc] initWithURL:URL entersReaderIfAvailable:NO];
  return safariViewController;
}

本來我還想將SFSafariViewController改成UIWebView,以觀察所有URL的流轉(zhuǎn)關(guān)系链沼。結(jié)果沒法使用UIWebView默赂,Google發(fā)現(xiàn)是UIWebView會(huì)直接報(bào)錯(cuò)。

Paste_Image.png

Google Auth返回的id_token已經(jīng)包含了用戶信息括勺,但是還是提供一個(gè)單獨(dú)的userinfo_endpoint去換取用戶信息缆八。

Paste_Image.png

手動(dòng)authorize流程如下所示。

11:09:02: Fetching configuration for issuer: https://accounts.google.com
11:09:02: Got configuration: OIDServiceConfiguration authorizationEndpoint: https://accounts.google.com/o/oauth2/v2/auth, tokenEndpoint: https://www.googleapis.com/oauth2/v4/token, registrationEndpoint: (null), discoveryDocument: [<OIDServiceDiscovery: 0x608000012970>]

11:09:02: Initiating authorization request <OIDAuthorizationRequest: 0x6000000ac180, request: 

//第一步疾捍,獲取auth code奈辰,參數(shù)都在URL里面。
https://accounts.google.com/o/oauth2/v2/auth?
response_type=code
&code_challenge_method=S256
&scope=openid%20profile
&code_challenge=zkJhG3SZa9vHx8P8TvikiEozUDNQwlJXnlskEe0wJGA
&redirect_uri=com.googleusercontent.apps.24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef:/oauth2redirect/
&client_id=24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef.apps.googleusercontent.com
&state=KX_4c-UQCxrshPrtHD75CLPoj80gipzxTr1r2hGNhus>

//拿到auth code
11:09:51: Authorization response with code: 4/SS-PVx_JADts0XLrN4VDQiK5QUOTd0qvKtYO_UZJO2E

//第二步乱豆,獲取access token和refresh token奖恰,參數(shù)都通過post發(fā)出去。
//Google Auth比較有特色的一點(diǎn)是沒有client_secret
11:09:52: Performing authorization code exchange with request [<OIDTokenRequest: 0x6080000ac360, request: <URL: https://www.googleapis.com/oauth2/v4/token, 
HTTPBody: code=4/SS-PVx_JADts0XLrN4VDQiK5QUOTd0qvKtYO_UZJO2E
&code_verifier=9zUuBzJkfD4y8Ei-424Cx-lWIwObhnSbC5_dOGZXSCk
&redirect_uri=com.googleusercontent.apps.24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef:/oauth2redirect/
&client_id=24408797720-p6d3uj34k564kl4s85o2d1rdgvlp7nef.apps.googleusercontent.com
&grant_type=authorization_code>>]

11:09:53: Received token response with accessToken: ya29.GltBBBYWx0rhh87WWK1oV0peHCI9_EwwoWWf4lUiwBc_--bTXv_Ag6OWdBU6SAHhYx5O6RdOsX1HMCPcELfeIlw-5rESYDuGmyRTqAuchGbHl1Ws-hC10O80YAmi

上面的參數(shù)中宛裕,code_challenge_method瑟啃、code_challengecode_verifier這三個(gè)看起來很神秘揩尸。它們是為了避免auth code被攔截而做了保護(hù)措施蛹屿。第一步通過code_challenge_methodcode_verifier做一次計(jì)算得到code_challenge。Authorization Endpoint會(huì)保存code_challenge相關(guān)的信息疲酌。第二步直接把code_verifier傳遞給token endpoint蜡峰,服務(wù)器端做一次對(duì)比了袁。如果對(duì)不上,就報(bào)錯(cuò)湿颅。詳細(xì)信息請(qǐng)參看:Proof Key for Code Exchange by OAuth Public Clients载绿。

Paste_Image.png
Paste_Image.png

繼續(xù)往下分析一下state這個(gè)參數(shù)的作用吧。state參數(shù)是為了防止CSRF攻擊油航,詳細(xì)信息請(qǐng)參看:OAuth2:忽略 state 參數(shù)引發(fā)的 csrf 漏洞 #68崭庸。In-App browser回跳到App時(shí),要檢查一下URL里面的state是否跟之前的state一致谊囚。

Paste_Image.png

OpenID Connect標(biāo)準(zhǔn)集里面包含一個(gè)Dynamic Client Registration的標(biāo)準(zhǔn)怕享,用于動(dòng)態(tài)注冊(cè)客戶端,不過我目前還沒有看到哪個(gè)OIDC服務(wù)器的Discovery里面有registration_endpoint镰踏,包括Google OIDC服務(wù)器函筋。

AppAuth客戶端是支持這個(gè)特性的,很多地方都會(huì)判斷是否配置了client_id奠伪。如果沒有配置的話跌帐,那么通過Dynamic Client Registration注冊(cè)一個(gè)客戶端。

if (!kClientID) {
  [self doClientRegistration:configuration
                    callback:^(OIDServiceConfiguration *configuration,
                               OIDRegistrationResponse *registrationResponse) {
    [self doAuthWithAutoCodeExchange:configuration
                            clientID:registrationResponse.clientID
                        clientSecret:registrationResponse.clientSecret];
  }];
} else {
  [self doAuthWithAutoCodeExchange:configuration clientID:kClientID clientSecret:nil];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绊率,一起剝皮案震驚了整個(gè)濱河市谨敛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滤否,老刑警劉巖脸狸,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異藐俺,居然都是意外死亡炊甲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門紊搪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜜葱,“玉大人,你說我怎么就攤上這事耀石。” “怎么了爸黄?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵滞伟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我炕贵,道長(zhǎng)梆奈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任称开,我火速辦了婚禮亩钟,結(jié)果婚禮上乓梨,老公的妹妹穿的比我還像新娘。我一直安慰自己清酥,他們只是感情好扶镀,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著焰轻,像睡著了一般臭觉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辱志,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天蝠筑,我揣著相機(jī)與錄音,去河邊找鬼揩懒。 笑死什乙,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的已球。 我是一名探鬼主播稳强,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼和悦!你這毒婦竟也來了退疫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤鸽素,失蹤者是張志新(化名)和其女友劉穎褒繁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馍忽,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棒坏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遭笋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坝冕。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瓦呼,靈堂內(nèi)的尸體忽然破棺而出喂窟,到底是詐尸還是另有隱情,我是刑警寧澤央串,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布磨澡,位于F島的核電站,受9級(jí)特大地震影響质和,放射性物質(zhì)發(fā)生泄漏稳摄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一饲宿、第九天 我趴在偏房一處隱蔽的房頂上張望厦酬。 院中可真熱鬧胆描,春花似錦、人聲如沸仗阅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霹菊。三九已至剧蚣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間旋廷,已是汗流浹背鸠按。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饶碘,地道東北人目尖。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扎运,于是被迫代替她去往敵國(guó)和親瑟曲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容