1、請求授權(quán)碼:
請求地址:
tokenEndpoint:https://accounts.google.com/o/oauth2/auth?access_type=offline' '&approval_prompt=force
回調(diào)地址:
_redirectEndpoint:http://localhost:53732
添加必要的參數(shù)鲁驶,得到完整地址:
https://accounts.google.com/o/oauth2/auth?access_type=offline &approval_prompt=force &response_type=code &client_id=818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.googleusercontent.com &redirect_uri=http://localhost:53732 &code_challenge=feEgljqpwBZROzS997ZdJaFMre_XWPZXY9tKOM1ehO4 &code_challenge_method=S256 &scope=openid+https://www.googleapis.com/auth/userinfo.email
總的來說是請求谷歌獲取授權(quán)碼钥弯。
2脆霎、在回調(diào)中,處理授權(quán)返回的響應(yīng)鹦马。請求令牌玖院。
在第一步的回調(diào)中拿到授權(quán)碼code,然后請求谷歌獲取 令牌
請求地址:
tokenEndpoint: https://accounts.google.com/o/oauth2/token
回調(diào)地址:(這一步這個回調(diào)沒啥用。难菌。)
_redirectEndpoint:http://localhost:53732
完整請求如下:
請求谷歌试溯,授權(quán)碼獲取令牌,是一個POST請求
返回的內(nèi)容為:
3郊酒、保存令牌遇绞。
拼裝成一個 credentials 對象
3、pub 源代碼分析
下面是代碼:
/// Gets the user to authorize pub as a client of pub.dev via oauth2.
///
/// Returns a Future that completes to a fully-authorized [Client].
Future<Client> _authorize() async {
var grant = AuthorizationCodeGrant(
_identifier, _authorizationEndpoint, tokenEndpoint,
secret: _secret,
// Google's OAuth2 API doesn't support basic auth.
basicAuth: false,
httpClient: _retryHttpClient,
);
// Spin up a one-shot HTTP server to receive the authorization code from the
// Google OAuth2 server via redirect. This server will close itself as soon as
// the code is received.
var completer = Completer();
var server = await bindServer('localhost', 0);
shelf_io.serveRequests(server, (request) {
if (request.url.path.isNotEmpty) {
return shelf.Response.notFound('Invalid URI.');
}
log.message('Authorization received, processing...');
var queryString = request.url.query;
// Closing the server here is safe, since it will wait until the response
// is sent to actually shut down.
server.close();
completer
.complete(grant.handleAuthorizationResponse(queryToMap(queryString)));
return shelf.Response.found('https://pub.dev/authorized');
});
var authUrl = grant.getAuthorizationUrl(
Uri.parse('http://localhost:${server.port}'),
scopes: _scopes,
);
log.message(
'Pub needs your authorization to upload packages on your behalf.\n'
'In a web browser, go to $authUrl\n'
'Then click "Allow access".\n\n'
'Waiting for your authorization...');
var client = await completer.future;
log.message('Successfully authorized.\n');
return client;
}
- 創(chuàng)建一個AuthorizationCodeGrant對象燎窘,該對象代表了使用OAuth2協(xié)議的授權(quán)碼授權(quán)流程摹闽。
- 使用AuthorizationCodeGrant對象的getAuthorizationUrl方法獲取授權(quán)URL,該URL將重定向到pub.dev的授權(quán)頁面褐健,以便用戶授權(quán)Pub作為客戶端訪問pub.dev的API澜汤。
- 啟動一個本地的HTTP服務(wù)器,并使用該URL響應(yīng)任何傳入的HTTP請求舵匾。服務(wù)器將綁定到本地地址localhost和隨機(jī)端口俊抵,以接收來自pub.dev授權(quán)服務(wù)器的響應(yīng)。
- 在瀏覽器中打開授權(quán)URL坐梯,用戶將在pub.dev網(wǎng)站上看到授權(quán)請求徽诲。用戶需要登錄并授權(quán)Pub訪問API。
- 授權(quán)服務(wù)器將重定向到之前啟動的本地HTTP服務(wù)器吵血,并將授權(quán)碼作為查詢參數(shù)傳遞谎替。HTTP服務(wù)器收到授權(quán)碼后,使用Completer將授權(quán)碼傳遞給Future蹋辅。
- 使用授權(quán)碼調(diào)用AuthorizationCodeGrant對象的handleAuthorizationResponse方法來獲取訪問令牌钱贯。
- 本地HTTP服務(wù)器響應(yīng)一個重定向,將用戶重定向回pub.dev/authorized侦另,以便用戶了解授權(quán)已成功完成喷舀。
- 關(guān)閉本地HTTP服務(wù)器,并返回已授權(quán)的HTTP Client對象淋肾,以便Pub可以使用OAuth2訪問pub.dev API硫麻。