1、请求授权码:
请求地址:
tokenEndpoint:https://accounts.google.com/o/oauth2/auth?access_type=offline' '&approval_prompt=force
回调地址:
_redirectEndpoint:http://localhost:53732
添加必要的参数,得到完整地址:
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
总的来说是请求谷歌获取授权码。
2、在回调中,处理授权返回的响应。请求令牌。
在第一步的回调中拿到授权码code,然后请求谷歌获取 令牌
请求地址:
tokenEndpoint: https://accounts.google.com/o/oauth2/token
回调地址:(这一步这个回调没啥用。。)
_redirectEndpoint:http://localhost:53732
完整请求如下:
请求谷歌,授权码获取令牌,是一个POST请求
image.png返回的内容为:
image.png3、保存令牌。
拼装成一个 credentials 对象
image.png
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;
}
- 创建一个AuthorizationCodeGrant对象,该对象代表了使用OAuth2协议的授权码授权流程。
- 使用AuthorizationCodeGrant对象的getAuthorizationUrl方法获取授权URL,该URL将重定向到pub.dev的授权页面,以便用户授权Pub作为客户端访问pub.dev的API。
- 启动一个本地的HTTP服务器,并使用该URL响应任何传入的HTTP请求。服务器将绑定到本地地址localhost和随机端口,以接收来自pub.dev授权服务器的响应。
- 在浏览器中打开授权URL,用户将在pub.dev网站上看到授权请求。用户需要登录并授权Pub访问API。
- 授权服务器将重定向到之前启动的本地HTTP服务器,并将授权码作为查询参数传递。HTTP服务器收到授权码后,使用Completer将授权码传递给Future。
- 使用授权码调用AuthorizationCodeGrant对象的handleAuthorizationResponse方法来获取访问令牌。
- 本地HTTP服务器响应一个重定向,将用户重定向回pub.dev/authorized,以便用户了解授权已成功完成。
- 关闭本地HTTP服务器,并返回已授权的HTTP Client对象,以便Pub可以使用OAuth2访问pub.dev API。
网友评论