如何通过Mojolicious::Plugin::OAuth2获取Refresh Token
解决Mojolicious::Plugin::OAuth2获取Google Refresh Token的问题
我来帮你搞定这个获取Google Refresh Token的事儿,之前用这个插件对接Google OAuth2的时候,也踩过类似的坑,咱们一步步来梳理:
1. 补全Google Provider的关键配置
你已经加了access_type => 'offline'(这是获取refresh_token的核心前提),但还缺一个关键参数prompt => 'consent'。因为Google现在默认规则是:用户首次授权后,后续重复请求不会再返回refresh_token,只有强制让用户重新确认授权时才会触发返回。修改你的插件配置:
plugin OAuth2 => { providers => { google => { key => 'somekey', secret => 'somesecret', redirect => 'http://localhost:3000/login/google', access_type => 'offline', prompt => 'consent', # 强制触发refresh_token返回 scope => join ' ', qw|some scopes|, } } };
2. 正确提取并存储Refresh Token
在你调用get_token_p的回调里,返回的$res对象其实已经包含了refresh_token字段,只是你之前只存了access_token。现在把它也妥善存储起来:
->then(sub { my $res = shift; return unless $res; # 同时保存access_token和refresh_token,建议存数据库而非仅session $c->session( token => $res->{access_token}, refresh_token => $res->{refresh_token} ); 1; })
⚠️ 注意:只有用户首次授权,或者你加了prompt => 'consent'让用户重新授权时,$res里才会有refresh_token。所以第一次拿到后一定要存到持久化存储(比如数据库),避免session过期丢失。
3. 正确调用get_refresh_token_p刷新Token
你之前调用这个方法报错,大概率是参数传递不对。这个方法需要传入已保存的refresh_token,以及provider标识。正确的使用姿势如下:
# 从存储中取出之前保存的refresh_token my $refresh_token = $c->session('refresh_token'); $c->oauth2->get_refresh_token_p(google => { refresh_token => $refresh_token }) ->then(sub { my $new_token_data = shift; # 更新session里的access_token,若返回新的refresh_token也一并更新 $c->session( token => $new_token_data->{access_token}, refresh_token => $new_token_data->{refresh_token} || $refresh_token ); # 后续逻辑:比如重新获取用户信息等 }) ->catch(sub { my $err = shift; $c->log->error("刷新Token失败: $err"); $c->render(text => "Token刷新出错: $err"); });
这个方法会自动用你配置的provider key和secret,向Google的Token端点请求新的access_token,部分情况下还会返回新的refresh_token,记得一并更新存储。
4. 额外排查要点
- 检查Google Cloud Console配置:确保你的OAuth同意屏幕已发布(测试阶段可用内部测试),且重定向URI和代码里的
redirect参数完全一致,包括协议(http/https)、端口和路径。 - 测试前清除旧授权:在Google账户的「安全」→「第三方应用访问权限」里找到你的应用并移除授权,这样第一次请求一定会返回refresh_token,方便验证逻辑。
内容的提问来源于stack exchange,提问作者simone
相关产品推荐
相关产品推荐

