hi
There is no good solution, we can only periodically check in the request if the user has changed the password.
You can override the SecurityStampValidator.ValidatePrincipalAsync method to validate it yourself in other ways.
https://github.com/dotnet/aspnetcore/blob/release/8.0/src/Identity/Core/src/SecurityStampValidator.cs#L129-L163
hi
JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.
You can try to use MemoryStorage in unit test.
var jobStorage = new MemoryStorage();
var options = new BackgroundJobServerOptions();
GlobalConfiguration.Configuration.UseStorage(jobStorage);
https://github.com/HangfireIO/Hangfire.InMemory https://github.com/perrich/Hangfire.MemoryStorage
You're welcome
hi
We fixed this >= 8.1.0, your ticket has been refunded.
Ok, I will ask my coworkers.
hi
You can check this: https://github.com/abpframework/abp/issues/4977#issuecomment-670006297
Add your TelegramExternalLoginProvider
hi
This is the source code of OAuthService.hasValidAccessToken()
https://github.com/manfredsteyer/angular-oauth2-oidc/blob/0211482b52df1f553c278acc812d86f39b04c97e/projects/lib/src/oauth-service.ts#L2420-L2436
You can override the AuthGuard to custom the logic.
Copy from https://support.abp.io/QA/Questions/6747/How-to-generate-access-token-in-backend-only-with-user-email#answer-3a10fd1e-cf4b-52f5-07f1-41607c71cdbe
Since the topic is the same, I want to raise my question here. Please reduce my tickets and guide me. I am very confused.
I have a web application that is hosted by Telegram Web App. This is a React application implemented in NextJS. The only thing I have access to is the token that Telegram produces. It gives me a hash string and its decryption key to validate that this request was sent by a user in Telegram. I want to auto-register every user who opened my Telegram app if they are not registered before. After confirming the token sent by Telegram, which has a userId, create a user with their Telegram ID as username and give them default roles. I also want users to access their account on the dashboard, which is the ABP admin web, without the need for a password using the Telegram Login widget, it has the same algorithm and I want to authenticate users using telegram token. What is the best flow I can use to handle this in ABP Studio MS Template (openid) please?
here is an overview of the data I can use to validate request:
using System;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Linq;
namespace Telegram
{
/// <summary>
/// A helper class used to verify authorization data
/// </summary>
public class LoginWidget : IDisposable
{
/// <summary>
/// How old (in seconds) can authorization attempts be to be considered valid (compared to the auth_date field)
/// </summary>
public long AllowedTimeOffset = 30;
private bool _disposed = false;
private readonly HMACSHA256 _hmac;
private static readonly DateTime _unixStart = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
/// <summary>
/// Construct a new <see cref="LoginWidget"/> instance
/// </summary>
/// <param name="token">The bot API token used as a secret parameter when checking authorization</param>
public LoginWidget(string token)
{
if (token == null) throw new ArgumentNullException(nameof(token));
using (SHA256 sha256 = SHA256.Create())
{
_hmac = new HMACSHA256(sha256.ComputeHash(Encoding.ASCII.GetBytes(token)));
}
}
/// <summary>
/// Checks whether the authorization data received from the user is valid
/// </summary>
/// <param name="fields">A collection containing query string fields as sorted key-value pairs</param>
/// <returns></returns>
public Authorization CheckAuthorization(SortedDictionary<string, string> fields)
{
if (_disposed) throw new ObjectDisposedException(nameof(LoginWidget));
if (fields == null) throw new ArgumentNullException(nameof(fields));
if (fields.Count < 3) return Authorization.MissingFields;
if (!fields.ContainsKey(Field.Id) ||
!fields.TryGetValue(Field.AuthDate, out string authDate) ||
!fields.TryGetValue(Field.Hash, out string hash)
) return Authorization.MissingFields;
if (hash.Length != 64) return Authorization.InvalidHash;
if (!long.TryParse(authDate, out long timestamp))
return Authorization.InvalidAuthDateFormat;
if (Math.Abs(DateTime.UtcNow.Subtract(_unixStart).TotalSeconds - timestamp) > AllowedTimeOffset)
return Authorization.TooOld;
fields.Remove(Field.Hash);
StringBuilder dataStringBuilder = new StringBuilder(256);
foreach (var field in fields)
{
if (!string.IsNullOrEmpty(field.Value))
{
dataStringBuilder.Append(field.Key);
dataStringBuilder.Append('=');
dataStringBuilder.Append(field.Value);
dataStringBuilder.Append('\n');
}
}
dataStringBuilder.Length -= 1; // Remove the last \n
byte[] signature = _hmac.ComputeHash(Encoding.UTF8.GetBytes(dataStringBuilder.ToString()));
// Adapted from: https://stackoverflow.com/a/14333437/6845657
for (int i = 0; i < signature.Length; i++)
{
if (hash[i * 2] != 87 + (signature[i] >> 4) + ((((signature[i] >> 4) - 10) >> 31) & -39)) return Authorization.InvalidHash;
if (hash[i * 2 + 1] != 87 + (signature[i] & 0xF) + ((((signature[i] & 0xF) - 10) >> 31) & -39)) return Authorization.InvalidHash;
}
return Authorization.Valid;
}
/// <summary>
/// Checks whether the authorization data received from the user is valid
/// </summary>
/// <param name="fields">A collection containing query string fields as key-value pairs</param>
/// <returns></returns>
public Authorization CheckAuthorization(Dictionary<string, string> fields)
{
if (fields == null) throw new ArgumentNullException(nameof(fields));
return CheckAuthorization(new SortedDictionary<string, string>(fields, StringComparer.Ordinal));
}
/// <summary>
/// Checks whether the authorization data received from the user is valid
/// </summary>
/// <param name="fields">A collection containing query string fields as key-value pairs</param>
/// <returns></returns>
public Authorization CheckAuthorization(IEnumerable<KeyValuePair<string, string>> fields) =>
CheckAuthorization(fields?.ToDictionary(f => f.Key, f => f.Value, StringComparer.Ordinal));
/// <summary>
/// Checks whether the authorization data received from the user is valid
/// </summary>
/// <param name="fields">A collection containing query string fields as key-value pairs</param>
/// <returns></returns>
public Authorization CheckAuthorization(IEnumerable<Tuple<string, string>> fields) =>
CheckAuthorization(fields?.ToDictionary(f => f.Item1, f => f.Item2, StringComparer.Ordinal));
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_hmac?.Dispose();
}
}
private static class Field
{
public const string AuthDate = "auth_date";
public const string Id = "id";
public const string Hash = "hash";
}
}
public enum Authorization
{
InvalidHash,
MissingFields,
InvalidAuthDateFormat,
TooOld,
Valid
}
}
hi
I still have not received your mail. You can send the link by https://wetransfer.com/
Thanks