Overview J'ai toujours voulu implémenter l'authentification en deux étapes, mais c'était plus facile que prévu en raison de l'existence d'une bonne bibliothèque.
https://github.com/wstrange/GoogleAuth
GoogleAuth est une bibliothèque Java côté serveur qui crée un mot de passe à usage unique basé sur l'heure (TOTP) tel que défini dans la RFC6238.
Si vous implémentez le côté serveur à l'aide de la bibliothèque ci-dessus, vous pouvez authentifier l'utilisateur à l'aide du jeton à usage unique émis par une application telle que Google Authenticator fourni par Google.
https://itunes.apple.com/jp/app/google-authenticator/id388497605?mt=8
https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=ja
Google Authenticator peut également être utilisé car il crée un jeton unique selon les spécifications TOTP.
Je pense que le flux sera le suivant.
https://github.com/yuizho/two-factor-auth-sample
Il s'agit du code d'implémentation de la partie Serveur dans le diagramme de séquence ci-dessus.
Le langage utilise Java.
Le processus d'enregistrement des informations utilisateur est triché en utilisant la carte de Singleton au lieu de DB.
Il s'agit de l'explication de l'exemple de code, ou presque de la façon d'utiliser la bibliothèque (Google Auth).
Vous pouvez émettre une clé secrète pour "user_id" avec le code ci-dessous et l'enregistrer dans une base de données.
GoogleAuthenticator gAuth = new GoogleAuthenticator();
GoogleAuthenticatorKey key = gAuth.createCredentials("user_id");
Avant d'exécuter le code ci-dessus, vous devez effectuer les préparatifs suivants.
Lorsque vous exécutez le createCredentials ci-dessus, GoogleAuth appelle la méthode saveUserCredentials de la classe d'implémentation de ICredentialRepository pour enregistrer la clé secrète.
public class MyCredentialRepository implements ICredentialRepository {
// ...
@Override
public void saveUserCredentials(String userId, String secretKey, int validationCode, List<Integer> scratchCodes) {
//Décrivez le processus pour enregistrer la clé secrète avec userId comme clé
}
}
Au fait, scratchCodes est un code à utiliser lorsque l'utilisateur perd le terminal, et il semble que 5 soient émis par défaut. https://github.com/wstrange/GoogleAuth#scratch-codes
Je ne pouvais pas tout à fait comprendre à quoi le validationCode était censé être (similaire à scratchCodes?) Si vous savez, apprenez-moi s'il vous plaît: arc
Je ne l'ai pas fait dans l'exemple de code, mais je pense que c'est une bonne idée d'implémenter le traitement de ces valeurs si nécessaire.
GoogleAuth implémente ICredentialRepository à l'aide de API Java ServiceLoader lors de l'exécution de createCredentials. Obtenez la classe et enregistrez le secretKey.
Créez un dossier META-INF / services à un emplacement où passe le chemin de classe, par exemple sous src / resource, et créez un fichier texte appelé com.warrenstrange.googleauth.ICredentialRepository.
Si vous décrivez le nom de classe d'implémentation de ICredentialRepository dans le fichier créé comme suit, Google Auth utilisera cette classe.
io.github.yuizho.twofactorauth.MyCredentialRepository
Lors du chargement des informations secrètes, y compris la clé secrète générée dans Google Authenticator, générez un URI au format suivant et convertissez-le en code QR.
otpauth://totp/<userId>?secret=<secretKey>&issuer=<applicationName>
e.g. otpauth://totp/test_user?secret=ZYWAZKOQLG3YHBSZ&issuer=two-factor-auth-sample
Voir ci-dessous pour plus de détails sur le format URI. https://github.com/google/google-authenticator/wiki/Key-Uri-Format
Vous pouvez obtenir le secretKey pour "user_id" à partir de la destination de sauvegarde comme ci-dessous, générer un jeton et vérifier s'il correspond au jeton transmis (celui obtenu avec Google Authenticator).
GoogleAuthenticator gAuth = new GoogleAuthenticator();
boolean isCodeValid = gAuth.authorizeUser("user_id", token);
À ce stade, GoogleAuth appelle la méthode getSecretKey de la classe d'implémentation de ICredentialRepository pour acquérir le secretKey de la même manière que lors de l'enregistrement de secretKey.
public class MyCredentialRepository implements ICredentialRepository {
// ...
@Override
public String getSecretKey(String userId) {
//Implémentation du processus d'obtention de secretKey de la table avec userId comme clé et de retour
}
}
Après cela, il générera un jeton basé sur la clé secrète acquise par Google Auth et l'horodatage actuel, et le comparera avec le jeton transmis au deuxième argument de GoogleAuthenticator # authorizeUser.
Il était donc relativement facile de mettre en œuvre l'authentification en deux étapes.
Cette fois, GoogleAuth est utilisé pour la bibliothèque côté serveur, mais vous pouvez bien sûr l'implémenter vous-même sans utiliser la bibliothèque.
Dans ce cas, je pense que vous devez implémenter le processus de génération de token TOTP tout en vous référant au RFC suivant, etc. (un exemple de code est également disponible). https://tools.ietf.org/html/rfc6238
Recommended Posts