Hello!
I've recently set up a passwordless system in ABP where users enter their phone number, receive an OTP on their mobile, and then input this OTP on the website. Once the OTP is verified, I need to generate a token that will be sent back to the client. This token is then used for accessing the app and retrieving data.
Could you guide me on how to generate this token to send back to the client? Thanks a lot! Please note that this token is something similar to machine-to-machine token when there is no human interaction or confirmation
ABP Framework version: v.7.3.2
Hello,
I've retrieved the client_id and client_secret from OpenIddictApplications, but I'm running into a snag: I keep getting an error that says "The specified client credentials are invalid." Do you have any idea what might be causing this?
Additionally, I could use some guidance on how to generate the token and include it in the payload.
I'm using a new grant type, and it's working wonderfully. Thank you so much for your help!
In our authentication server project, I've added the setup and grant type configurations like above image. However, when I attempt to run the API through the endpoint 'domain/connect/token', I encounter an issue.
hi @maliming, do you have any ideas?
yes @maliming, pls check your mail
You can also make it simple.
public class PasswordlessExtensionGrant : ITokenExtensionGrant { public const string ExtensionGrantName = "PasswordlessExtensionGrant"; public string Name => ExtensionGrantName; public async Task<IActionResult> HandleAsync(ExtensionGrantContext context) { // get phone number from request var phoneNumber = context.Request.GetParameter("phoneNumber")?.Value?.ToString(); if (string.IsNullOrEmpty(phoneNumber)) { return new ForbidResult(new[] { OpenIddictServerAspNetCoreDefaults.AuthenticationScheme }, properties: new AuthenticationProperties(new Dictionary<string, string> { [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant }!)); } // retrieve user var userRepository = context.HttpContext.RequestServices.GetRequiredService<IRepository<IdentityUser, Guid>>(); var user = await userRepository.FirstOrDefaultAsync(x => x.PhoneNumber == phoneNumber); if (user == null) { return new ForbidResult(new[] { OpenIddictServerAspNetCoreDefaults.AuthenticationScheme }, properties: new AuthenticationProperties(new Dictionary<string, string> { [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant }!)); } var principal = await context.HttpContext.RequestServices.GetRequiredService<IUserClaimsPrincipalFactory<IdentityUser>>().CreateAsync(user); // retrieve generic user claims var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService<IUserClaimsPrincipalFactory<IdentityUser>>(); var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user); claimsPrincipal.SetScopes(principal.GetScopes()); claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes())); // retrieve abp user claims var abpClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>(); var abpClaimsPrincipal = await abpClaimsPrincipalFactory.CreateAsync(claimsPrincipal); await context.HttpContext.RequestServices.GetRequiredService<AbpOpenIddictClaimsPrincipalManager>().HandleAsync(context.Request, abpClaimsPrincipal); return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, abpClaimsPrincipal); } private async Task<IEnumerable<string>> GetResourcesAsync(ExtensionGrantContext context, ImmutableArray<string> scopes) { var resources = new List<string>(); if (!scopes.Any()) { return resources; } await foreach (var resource in context.HttpContext.RequestServices.GetRequiredService<IOpenIddictScopeManager>().ListResourcesAsync(scopes)) { resources.Add(resource); } return resources; } }
I noticed the scope of this token is a bit limited. Could we look into adding more scope to it? This way, we can ensure it meets all our needs more effectively. Thanks for considering this!
hi
curl --location 'https://localhost:44369/connect/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=PasswordlessExtensionGrant' \ --data-urlencode 'client_id=DemoNewGrantType_App' \ --data-urlencode 'phoneNumber=0344446301' \ --data-urlencode 'scope=openid offline_access DemoNewGrantType' { "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg0NzZDOTUwQjYxOTY2MkY2QUU4MTlGOUVDNzdEMzI0QkMyNDFFRDQiLCJ4NXQiOiJoSGJKVUxZWlppOXE2Qm41N0hmVEpMd2tIdFEiLCJ0eXAiOiJhdCtqd3QifQ.eyJzdWIiOiI3NWZjNDI1Yy1mMDY3LTlmODQtZWNkMy0zYTBmNDZlY2UxZWUiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AYWJwLmlvIiwicm9sZSI6ImFkbWluIiwiZ2l2ZW5fbmFtZSI6ImFkbWluIiwicGhvbmVfbnVtYmVyIjoiMDM0NDQ0NjMwMSIsInBob25lX251bWJlcl92ZXJpZmllZCI6IlRydWUiLCJlbWFpbF92ZXJpZmllZCI6IkZhbHNlIiwidW5pcXVlX25hbWUiOiJhZG1pbiIsIm9pX3Byc3QiOiJEZW1vTmV3R3JhbnRUeXBlX0FwcCIsIm9pX2F1X2lkIjoiNzRjOTkyZjQtYzNjMS1kYThmLWM5MzAtM2EwZjQ2ZjQ5NjUwIiwiY2xpZW50X2lkIjoiRGVtb05ld0dyYW50VHlwZV9BcHAiLCJvaV90a25faWQiOiI4MTgzODlhOC1mNDQxLTVjODgtNDZmYS0zYTBmNDZmNDk3ZTAiLCJhdWQiOiJEZW1vTmV3R3JhbnRUeXBlIiwic2NvcGUiOiJvcGVuaWQgb2ZmbGluZV9hY2Nlc3MgRGVtb05ld0dyYW50VHlwZSIsImp0aSI6ImQ2MTU5ZjBjLTFlMDQtNDc0NC1iM2EyLWY4ZmY4NGEyYTQyMiIsImV4cCI6MTcwMTY5NjE1NSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNTYvIiwiaWF0IjoxNzAxNjkyNTU1fQ.KZs_2YXYy2sUjQ7K5nOSYKf5MRDBHgbr5AhKeIy6LIworGs6lFXDFde7IdILagvSlxbK7qDC2QdN1pBOemDTyckUtPHKne5hfvX7ZIQrS5FnEPkff9rMqH9E8rwA9x0DukiH5HIuhT5qLps_sXvVhngp1oa7fwiV6_WcfDud_F_qgimOcfXuPzL_ifSYe1Vb8b8vf-lKU5t8ucrrGM9aPBTa9TOs7-5gMabRcksbDhGtVyyTOXRtItI242lZR5msDTElgF59QQNAPXJzKH6cY-A-_2NTyI7LYmeqY5_q43xIfWAEF0seHoWwTSgb89AdZfF-qChQUGIjcX7JyHpdOw", "token_type": "Bearer", "expires_in": 3598, "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg0NzZDOTUwQjYxOTY2MkY2QUU4MTlGOUVDNzdEMzI0QkMyNDFFRDQiLCJ4NXQiOiJoSGJKVUxZWlppOXE2Qm41N0hmVEpMd2tIdFEiLCJ0eXAiOiJKV1QifQ.eyJzdWIiOiI3NWZjNDI1Yy1mMDY3LTlmODQtZWNkMy0zYTBmNDZlY2UxZWUiLCJvaV9hdV9pZCI6Ijc0Yzk5MmY0LWMzYzEtZGE4Zi1jOTMwLTNhMGY0NmY0OTY1MCIsImF6cCI6IkRlbW9OZXdHcmFudFR5cGVfQXBwIiwiYXRfaGFzaCI6Iks2OHQtdFBFOFpBbk1TZFh5UFIza3ciLCJvaV90a25faWQiOiIxNmMzOWNjYy1lYmY4LTZjYTctYjYzOC0zYTBmNDZmNDliZTMiLCJhdWQiOiJEZW1vTmV3R3JhbnRUeXBlX0FwcCIsImV4cCI6MTcwMTY5Mzc1NSwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNTYvIiwiaWF0IjoxNzAxNjkyNTU1fQ.eeB5O1R-a8lXnWaDsce1jSc6v8XK0CKYzYLAoo1odEtJbjubn45k_HZbXOXXuesUol-eB3rWYhtkvtZDgzVh6HO40-c39jH2BBitRuYgf9nPTwV6qrcKbJFZ2Z4_RRuJJyT4eK8kNrNPiovHm2yzrGLP0beylBPDv0UQz7E5CFcaZC6kPF8m1SXHx58hgdo9vLHxuAPkDxiyX4Q3isa3lijDdUK1ubtRhEEy5mGxaFLdNHY0IgVSMydmghPPGTqVPkHjHVjOxp1Zz85f7iKIjLRk--y5FD8X93NraEmynwR-pK05cKD7I-kEcpGkfDpdIyVbqhQHdGNUgW3VW7HuJQ", "refresh_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZDQkMtSFM1MTIiLCJraWQiOiI4NDc2Qzk1MEI2MTk2NjJGNkFFODE5RjlFQzc3RDMyNEJDMjQxRUQ0IiwidHlwIjoib2lfcmVmdCtqd3QiLCJjdHkiOiJKV1QifQ.KeJzUD3N04KShYV2jUfsIRsloryqMXQLjsXMtRAbkW2pMbGunkLDHZTSEIypj9ECQQvjgp9rU2a2EGRLcbG6OsLIaY7e66cNywY8PvPjMJXOKNYAY8y1Xza2k4if8N5vvEh44HeqeEEQa3a2J0pmgeuJUT6hdbzKZt-fjmlBI9H23cYN0fVqPVS6Uf9yE45mnO-KvfuWeOxIZnOqvsX35j9EOsoYlJrhSwvvUPX5YGD-KOiyE9Erf0oQNV99UMSFvDHeKBPXMZvEXhboIkbaqoOLOlohP0DbkZTylZTk22n1Z6lQ-oPZMJqoykeAglbDiHn90xl1gA9mPwoHtZp2tQ.b4rnMNjBD72M9I9qdx29fQ.zh0bsUNMfXngES1Zo5jWI0WDgKIX4PekAsohDDUZFAaaZisqJWCFNudTIakzmLkQm1rQK19xx-94pyR03Tj8bzwopOmiYltLFmhWqyrh8xOeuTjYV2d8CByjyLD-xRu9kFSjqUHX2_RbN75yFBa-TlBs3b42fvNuEVbCB4CXvIXVfY1_jipyPRMCkWbO9s80qYrUgf9IfUvasfPLWANXxoh37eXz71cLAGv6cQj25TN4qUGO9S9PxenkuFUXFSOlqONYWGp0ZWEomWslgtpBkt8Ls2T8KqhdQqnNslAmCRZOd0kN0kPyF2a1S19Suhb7RYnd7XGKXSJZogDZTbkDN_gnGLvhD4yMbZX1ruke8p9Ef2l9YKKBe7zaUHSVMfpumLaFQRA-thQBo-V_ahRSnr0oQ6EM-5qL8DTpaJZXutYCJcpR3pscCMi5au-1pAerfDeKwpLHMFZJweyJItGgsfz1ouva6Fqpw_mTbucd5qT7xAn7hL9mXbUd9sGW12XE4a8uCslCi8h_EBD59N6ZwCsVDcvKaz1xggDsBbK0K8iO46AqiDVSXK4qjYrmyO1ouMUJrd9zfpp21y0-56OGpoBmt9JX2l1gdZyt6nItvipGhf7UZxH01WU81VKYeo_YvF7Y92HtQIIjQ1zesVUHJmbkgAC-80TGBRkI-wvkNm3N7tb8-gLOrJy8rHOuEjAB1dUFnaSHw7jtPLKE4uL2H2Ol8eV0Vp-LBKAzp8H-4tVUzqTR0P0NjVKT_1GeqhHoU-cNlwI9hKPW4Fh5Y6ETd3n1KmAJFj002WAZv_69MiE9OT7OZVjEzw9hjTw1vynUJ9yVwJmP8F6aAYzej5O-iQ1UA9jBnlAD0gbIe1cRabQAlP022NxzKJhyKMZN4xkuXxFMxMtqRn-2bwdPClJtM1IwGumFA_prp-e9Fi3eFVrnaXAL4XVhROlMvqwJ52vRKZ41zqkgMIwLC9D_zCtOXqjIckyK1VPZc3TUGGMCmCkGBM1m8Tw35qgtUfPwC1kybk2msG58TnytQzPZjJct-2l1w1N7uA6_xiMcEfAl1CYFTqeqGTaCuXmohFM_ObnOPQMOg1v-56QbbmSZOq6uSnFROEmDkfR4VMVwcvLtVAB0E1fF3y3W5z_G7g0iHHMeOoVvTs1xEwfvlUvvtKVSnV2HtoNT9tbGEnaAozTPeXEWaXgvz0zY4BZtKgeuezLNT9B8B5SVo4vhRrZFjlhp-kcfjK5idRTy1rMY1NT-gwNSJlC_JgOG-lfJ8qsOxg0vDdxa29funISTqfhw0aDFAhh9WFaFK9jO31hlu0cIAxs6Ys-Bpjq3U1GmwguNtJ3g8Ira_NwD-r9zBtf6GKPlxLaf0IJQsYSYVfBJiQ4nR9_59sAf-qMk_BQxYdzQ_qBci1-UC2D8EI-M4r1r1iMurWZ8rVMd1Z1Pp7RaRGuqRc748GXUg51NG6dLXmtDDHsigMHMM0cj0x3hs7kUTm5CsUA0WhUzA641Ej6M-tKZ-2Bm3q6DT7YXW38sqvb1k-F85bZxMBqxQcMu23Ox3r82YAqMy0pSKslpCvN57jhWg-ucnWGt3g851J13FxJTNq1HoFDQ70IRNG06C7uy_zK5JfsGPm-WBOnY9yukzaEiqXsArgzlRUpqR2qq357c97RUenzLDWw6KFj7JfpCapKPK_dsPkw_FPbxUF0zeYXQEfDegoALEGI53YIfrjm8XPqIw1PlqNP4zegxpkpJ8cy0CBmyQzU4FPpenEG3GNGVqBhfvzjsI1IcsjtYb0CBjC0Uw2QFbF_qPPb8e7TLrg3qMQ9xYbmmoTaId6CEWKMfxVOgDzXacbkO5dS9H7eY_UaG0NjfIuz1-4Z3KdJZ6xljjNwnzfW3i7hbwRlAE664gtorbVCl0mTmZM6LSmsJhKjKzWfSusZQi62WMxOfh6QUkAYOMDMdxIbPwcu4KOvTcNvVOB8YpLkqHch-0RUCLiNeFOjsGG-RKhtg3hxIBN7RCaEI-Kv4hSUK-dd_4hUXQyOsPI3ftuJdTvRXVD7sINA-nh-DIafI_G0tLHryeIkVeC_1jPb6_ynlkb9IWDJ0G7AtYl6ivl85z4b4Z2YqQoZWv1FEidPXq_-S9E-dazmjiFMf-Mu7mCiJ7InOrZmrWlBsy4N-c2nQfkSsnmliUyKdx2ISyi0M8EdDJF5X7tHyLTO9Zu7VjayFGKXJHFB2dZxEUt6xrw665k7WdUeH9iiJBNRWXNpH6H6cC8SiHal4W4Hu97SSAuTJ6oyHviZkXkYjM8a33BGAIpGdKqauvBbutTcPA1x1mmOeasAsd9G_F92bmSZGs9gJrmK_YHrEXrU7vInM5MJtmC1GmTj0ayoen8XlKJ4LItZm6sV6UoJrILToU1t3vRJ-poCJ6F8GjAHq3ltGaydFjKkXlzGXRkxBWOSs5BXVIhJE6V287s0VD2jLhdLHsHPtusbtyfbe8RmqynnA4jBPxieM_xvRkhCYATrhgF-0vwJcrXFKXcYcig.K6TpJpgb98WJjt8_fgWQS98m42FD3pKaUvlQ1ZiIdMQ" }
I've added more setup and it's not working.
var issuerUrl = configuration["AuthServer:Authority"]; PreConfigure<OpenIddictServerBuilder>(builder => { builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration));
builder.SetIssuer(new Uri(issuerUrl)); builder.SetAuthorizationEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/authorize"))); builder.SetTokenEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/token"))); builder.SetIntrospectionEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/introspect"))); builder.SetLogoutEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/logout"))); builder.SetRevocationEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/revocat"))); builder.SetUserinfoEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/userinfo"))); builder.SetDeviceEndpointUris(new Uri(Url.Combine(issuerUrl, "connect/device"))); builder.SetCryptographyEndpointUris(new Uri(Url.Combine(issuerUrl, ".well-known/jwks"))); builder.SetIdentityTokenLifetime(TimeSpan.FromMinutes(60)); builder.SetAccessTokenLifetime(TimeSpan.FromMinutes(60)); builder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(60)); builder.SetDeviceCodeLifetime(TimeSpan.FromMinutes(60)); builder.SetRefreshTokenLifetime(TimeSpan.FromMinutes(60)); builder.SetUserCodeLifetime(TimeSpan.FromMinutes(60)); builder.Configure(openIddictServerOptions => { openIddictServerOptions.GrantTypes.Add(PasswordlessExtensionGrant.ExtensionGrantName); }); });