メモ。
ToDo
- Auth0のユーザAPIやToken inspectionを使わずに、
email_verified
でEmailアドレスの取得を済ませたい気持ちがある - LockはEmailアドレスの記憶までは面倒を見てくれないっぽい
... 書いておいてアレだけどソーシャルログインで十分だな。。
何ができるの?
Auth0 ( https://auth0.com ) は7000アカウントまで対応した無料プランを持っており、この無料プランには、いわゆるPasswordless認証機構が含まれている。
これを使うことで、アカウントを要求するWebサイトでよくある:
- E-mailアドレスを入力させる
- ユーザにE-mailが送られてくる
- ユーザがE-mail中のリンクをクリックする
- サイトにログイン
というフローを無料で実現できる。認証結果はOpenID Connectで言うところのID Tokenで提供されるため、ID TokenをWebアプリケーション側で検証してやる(& 必要に応じて専用のトークンを更に振り出す)必要はある。
Auth0側でやること
- Applicationを作る( https://manage.auth0.com/#/applications ) - これにより、Client IDやClient Secretが発行される。
- (APIを作る( https://manage.auth0.com/#/apis ) - これにより、OpenID Connectで言うところのaudienceを作成できる。(Auth0上では Identifier と呼ばれる))
- Hosted page( https://manage.auth0.com/#/login_page )をPasswordless用に書き換える (重要)
- Connection から Passwordlessを有効にする
Auth0のログインページはLock( https://auth0.com/docs/libraries/lock/v11 )によって提供されているが、Passwordless用のものは別物になるため書き換えが必要になる。ポイントは:
-
var lock = new Auth0LockPasswordless(config...
のようにAuth0LockPasswordless
をインスタンシエートする -
passwordlessMethod: 'link'
をconfig
に加える
標準のログインページではPasswordlessは選択肢に表われず、Connectionsから有効にするだけでは使えないことになる。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Sign In with Auth0</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<!--[if IE 8]>
<script src="//cdnjs.cloudflare.com/ajax/libs/ie8/0.2.5/ie8.js"></script>
<![endif]-->
<!--[if lte IE 9]>
<script src="https://cdn.auth0.com/js/base64.js"></script>
<script src="https://cdn.auth0.com/js/es5-shim.min.js"></script>
<![endif]-->
<script src="https://cdn.auth0.com/js/lock/11.11/lock.min.js"></script>
<script>
// Decode utf8 characters properly
var config = JSON.parse(decodeURIComponent(escape(window.atob('@@config@@'))));
config.extraParams = config.extraParams || {};
var connection = config.connection;
var prompt = config.prompt;
var languageDictionary;
var language;
if (config.dict && config.dict.signin && config.dict.signin.title) {
languageDictionary = { title: config.dict.signin.title };
} else if (typeof config.dict === 'string') {
language = config.dict;
}
var loginHint = config.extraParams.login_hint;
// Available Lock configuration options: https://auth0.com/docs/libraries/lock/v11/configuration
var lock = new Auth0LockPasswordless(config.clientID, config.auth0Domain, {
auth: {
redirectUrl: config.callbackURL,
responseType: (config.internalOptions || {}).response_type ||
(config.callbackOnLocationHash ? 'token' : 'code'),
params: config.internalOptions
},
/* additional configuration needed for custom domains
configurationBaseUrl: config.clientConfigurationBaseUrl,
overrides: {
__tenant: config.auth0Tenant,
__token_issuer: 'YOUR_CUSTOM_DOMAIN'
}, */
assetsUrl: config.assetsUrl,
allowedConnections: connection ? [connection] : null,
rememberLastLogin: !prompt,
language: language,
languageDictionary: languageDictionary,
theme: {
//logo: 'YOUR LOGO HERE',
//primaryColor: 'green'
},
prefill: loginHint ? { email: loginHint, username: loginHint } : null,
closable: false,
defaultADUsernameFromEmailPrefix: false,
passwordlessMethod: 'link'
// uncomment if you want small buttons for social providers
// socialButtonStyle: 'small'
});
lock.show();
</script>
</body>
</html>
提供されるToken
適当にscope = openid profile
としてOAuth2すると、以下のようなTokenが払い出される。
Access Token
{
"iss": "https://yuni.auth0.com/",
"sub": "email|5c2e8f08e8fd56b4e565b117",
"aud": [
"https://stripe.local",
"https://yuni.auth0.com/userinfo"
],
"iat": 1546559613,
"exp": 1546566813,
"azp": "as6bZ2s623qL3ga6UI1LqxySAPXFwgwq",
"scope": "openid profile"
}
Access Tokenにはe-mailアドレスそのものは含まれていない。 profile
スコープを要求したうえで、ID Tokenを取得する必要がある。
ID Token
{
"nickname": "mjt",
"name": "mjt@cltn.org",
"picture": "https://s.gravatar.com/avatar/5cbf298165e52d62a8e0fc0114ce9d48?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fmj.png",
"updated_at": "2019-01-03T23:53:31.322Z",
"iss": "https://yuni.auth0.com/",
"sub": "email|5c2e8f08e8fd56b4e565b117",
"aud": "as6bZ2s623qL3ga6UI1LqxySAPXFwgwq",
"iat": 1546559613,
"exp": 1546595613,
"at_hash": "1JMASj-DhLGRRmtNIDPVtg",
"nonce": "qwerty"
}
name
がEmailアドレスに相当する ...って email_verified
とかじゃダメなんだろうか。。(TODO)