Я столкнулся с действительно странной проблемой и почти перепробовал все возможные комбинации, которые мне удалось решить. К сожалению, код qr, который сканирует приложение Google Authenticator, не соответствует тому, что вычисляет Otp. NET на стороне сервера.
Я использовал тот же ключ, алгоритм для генерации кода Qr на стороне клиента, который затем сканируется и передается на сторону сервера для изменения, которое не удается. Следующим является исходный код для стороны сервера:
Код стороны обслуживания. (Генерация ключа / секрета) Используемая библиотека: https://github.com/kspearrin/Otp.NET
var otpSeed = KeyGeneration.GenerateRandomKey(OtpHashMode.Sha512);
userIdentity.OTPSeed = otpSeed;
customResponse.Add(TwoFASeedKey, Base32Encoding.ToString(key));
customResponse.Add("OtpHashMode", "SHA512");
customResponse.Add("Username", "alice@demo");
customResponse.Add("Issuer", "demo Issuer");
При использовании следующего кода для изменения кода OtpCode, отправляемого со стороны клиента.
public bool VerifyOtp(byte[] otpSeed, string otpCode) // otpSeed is the same secret which is being generated at the first step.
{
var totp = new Totp(otpSeed, 30, OtpHashMode.Sha512, 6);
return totp.VerifyTotp(otpCode, out var timeWindow, VerificationWindow.RfcSpecifiedNetworkDelay)
}
, в то время как ниже приведен код на стороне клиента, который извлекает вышеуказанные данные в качестве обратного вызова.
Clientside
Используется библиотека для генерации метода QRCode: (toDataURL) из https://www.npmjs.com/package/qrcode#createtext -опций
public void postLogin(){
await this.oauthService.fetchTokenUsingPasswordFlow(username, password)
.then(response => {
const state = response['2FAState'];
const seed = response['2FASeed'];
const issuer = response['Issuer'];
const userName = response['Username'];
const otpHashMode = response['OtpHashMode'];
this.username = userName;
this.totpUri = this.makeTotpUri(seed, issuer, userName, otpHashMode);
toDataURL(this.totpUri).then((data_url) => {
this.otpQrCodeUrl = data_url; // This OtpQrCode bound with img src at HTML, which shows QR code png image at screen. Google Auth easily scans that image and shows the 6 digit code.
});
});
}
private toTotpUri({ secret, accountName, issuer, algo, digits, period }:
{
secret: string; accountName: string; issuer: string;
algo: string; digits: number; period: number;
})
{
return `otpauth://totp/${encodeURI(issuer || '')}
:${encodeURI(accountName || '')}
?secret=${secret.replace(/[\s\.\_\-]+/g, '').toUpperCase()}
&issuer=${encodeURIComponent(issuer || '')}
&algorithm=${algo}
&digits=${digits || 6}
&period=${period || 30}`;
}
public makeTotpUri(seed: string, issuer: string, userName: string, otpHashMode: string): string {
return this.toTotpUri({ secret: seed, accountName: userName, issuer,
algo: otpHashMode, digits: 6, period: 120 });
}
Секрет выборки, сгенерированный из RandomKeyGenerator из Otp. NET
ZYXHYYDP7TJBALMCFZBMLT7ALV3RU53UQ3JAULN7VGFVWEVDR4DLLHJAL7CFMZ4WDIDDWSMZ7O5D73L7KFIR6V3BYNTYJDCIG4KILRQ=
Примечание. Я попытался сгенерировать 6 di git Otp-код вручную на стороне сервера с помощью ComputeHash
и изменил его с помощью Otp.Varify, он работал там. Но когда код сканируется из Google Auth, переданный код никогда не совпадает. Я понятия не имею, почему неправильный код генерируется методом QRCode.toDataURL. Любая помощь будет очень признательна, так как я застрял здесь.