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
hi
because ISettingManager is not available.
You can depend on the AbpSettingManagementDomainModule and use ISettingManager, Your MicroService.HttpApi.Host already depends on SettingManagement module.
hi
The packages of Identity.Pro are https://abp.io/packages?moduleName=Volo.Identity.Pro
Please remove the Volo.Abp.Identity packages and use packages of Volo.Identity.Pro
hi
You can try to set ValidationInterval of SecurityStampValidatorOptions. The default is 30 minutes.
If this value is too small, it may affect performance.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.securitystampvalidatoroptions.validationinterval?view=aspnetcore-8.0