Comments (65)
My pleasure. Don't hesitate if you need additional details or have any other question ๐
from openiddict-core.
I did, but I see now the values are not correct , thanks
from openiddict-core.
nevermind, I see thats the case for the server above
from openiddict-core.
Yeah I found about ASPNETCORE_FORWARDEDHEADERS_ENABLED = true
the hard way
from openiddict-core.
No, OpenIddict uses a unique state/correlation cookie name per authentication demand, so even if you start concurrent operations, all of them should be able to complete successfully (unless you started hundreds of demands at the same time and are hitting cookie limits, of course, but it's not the case here).
from openiddict-core.
Thanks for your help, will do a final compare with your samples and see if I can find anything
from openiddict-core.
This thread is getting a bit long and I believe the initial question (making the Dantooine sample work) has been addressed.
Feel free to open a separate thread if you want to discuss more complex scenarios ๐๐ป
from openiddict-core.
Hey @meywd,
Thanks for sponsoring the project!
Your Dantooine Sample has the Auth Server and the BFF Server each connecting to a different Context and Database, why is that?
The idea behind the decoupling is that the WebAssembly client and its associated BFF server are independent from the authorization server, that may even be managed by a completely different organization (note: the BFF server uses the OpenIddict client, which is stateful and requires an EF Core context for token persistence).
Are there any issues in the code above?
Also any idea why the Token above in BFF Proxy call is null.
Your snippet uses the MSFT OIDC handler instead of the OpenIddict client that is leveraged by the Dantooine sample. Unlike OpenIddict, the MSFT OIDC handler doesn't support storing both the frontchannel access token (returned as part of the authorization response) and the backchannel access token (returned as part of the token response). Instead, it just prefers the backchannel access token when available and stores it using the generic access_token
name.
That's why your call to GetTokenAsync(CookieAuthenticationDefaults.AuthenticationScheme, Tokens.BackchannelAccessToken)
doesn't return anything. Either migrate to the OpenIddict client or if you prefer using the MSFT OIDC handler, use GetTokenAsync(CookieAuthenticationDefaults.AuthenticationScheme, "access_token")
instead.
Hope it'll help.
from openiddict-core.
Will try that, thanks for the quick answer.
I guess I understand the sample more, like a provider and a local user with permissions, being a BFF made it just a gateway in my mind,I didn't consider it to be the main app, In my case I want the API to have the user management, and the BFF simply for handling cookies and refresh tokens and consolidate API calls.
So in my scenario, switching to the openiddict client should be enough? And is there a problem with having the API manage the users?
Also when I want to connect the SPA, should it be a separate client? Or if it depends on the BFF to do auth and save the cookies be enough if all calls go through it?
And I need to be able to do API to API calls with app auth, what should I do to support that?
from openiddict-core.
So in my scenario, switching to the openiddict client should be enough? And is there a problem with having the API manage the users?
Yep, it should be enough. No problem implementing user management as an API, it's a common approach.
Also when I want to connect the SPA, should it be a separate client? Or if it depends on the BFF to do auth and save the cookies be enough if all calls go through it?
The whole point of having a BFF - backend-for-frontend - is to act as a proxy for your SPA, that will exclusively use cookie authentication instead of token authentication (and isn't considered as an OIDC client: the real client is the BFF server itself).
If you implement OIDC support at the SPA level (e.g using the oidc-client-ts
library) and add a client registration for it, then a BFF is completely useless here. Both options are possible and it's up to you to decide what approach you prefer (see #1918 and openiddict/openiddict-samples#180 for related discussions)
And I need to be able to do API to API calls with app auth, what should I do to support that?
You need the client credentials grant for that. See https://github.com/openiddict/openiddict-samples/tree/dev/samples/Aridka.
from openiddict-core.
Thank you Kevin.
from openiddict-core.
for now I went for BFF with EFCore, had to copy from the sample to make it work, so its only using EF for the tokens? its not doing anything with the dbcontext like users and so on, anyway it now gives:
The introspection request was rejected because the access token was issued to a different client or for another resource server.
the scope seems to be set right so not sure whats the issue.
from openiddict-core.
The introspection request was rejected because the access token was issued to a different client or for another resource server.
the scope seems to be set right so not sure whats the issue.
You're getting this error because your API is not allowed to introspect the access token. You likely didn't add a resource to your scope that will be used by OpenIddict to attach the correct audience(s) to the access tokens.
See:
- https://github.com/openiddict/openiddict-samples/blob/444be7d14de7932fcf103454682c07b45e1ba146/samples/Zirku/Zirku.Server/Program.cs#L210-L213
- https://github.com/openiddict/openiddict-samples/blob/444be7d14de7932fcf103454682c07b45e1ba146/samples/Zirku/Zirku.Server/Program.cs#L184-L195
- https://github.com/openiddict/openiddict-samples/blob/444be7d14de7932fcf103454682c07b45e1ba146/samples/Zirku/Zirku.Server/Program.cs#L286
from openiddict-core.
I am trying to add Introspection and client credentials to the APIs, I see Introspection is done with the AddValidation
call, how to add the AllowClientCredentialsFlow is it the AddServer
or AddClient
?
from openiddict-core.
how to add the AllowClientCredentialsFlow is it the AddServer or AddClient ?
Both:
- Client: https://github.com/openiddict/openiddict-samples/blob/444be7d14de7932fcf103454682c07b45e1ba146/samples/Aridka/Aridka.Client/Program.cs#L16
- Server: https://github.com/openiddict/openiddict-samples/blob/444be7d14de7932fcf103454682c07b45e1ba146/samples/Aridka/Aridka.Server/Startup.cs#L66
from openiddict-core.
now that I think about it, yeah, thanks
from openiddict-core.
but then there will be 3 calls?
from openiddict-core.
And the adventure continues
Calling from SPA to BFF, it redirects to Auth server were I login, then back to BFF and I get this error:
No correlation cookie associated with the specified state can be found. Please try logging in again. If the error persists, please contact the website owner.
from openiddict-core.
This error happens when OpenIddict's ASP.NET Core client integration cannot find the antiforgery cookie created during the challenge operation while handling the callback/redirection request (most likely because it's not sent by the browser).
Can you share a Fiddler trace?
from openiddict-core.
from openiddict-core.
I don't see neither the challenge response nor the faulted redirection/callback request in these traces.
That said, I see your authorization server is accessed without using a HTTPS address, which may be related. Try to fix that to see if it helps.
from openiddict-core.
Yeah I am having a problem making https work in docker, which is almost the same in Azure Container Apps which acts as a proxy and terminates https
from openiddict-core.
The correlation cookie is correctly returned by the OpenIddict client during the challenge phase...
HTTP/2 302
date: Fri, 08 Mar 2024 15:32:01 GMT
server: Kestrel
access-control-allow-origin: *
location: http://host.docker.internal:7774/connect/authorize?client_id=64176522-c3a3-441d-beb8-689b2524b7c3&redirect_uri=https%3A%2F%2Flocalhost%3A7773%2Fcallback%2Flogin%2Flocal&response_type=code&scope=openid%20profile%20api%20workflow&nonce=NJ4dpWLs3jadTF-6hL42GjvHkNJ-VfLExd0IWePuqOo&code_challenge=grI3bBW4_4il88ZheGjVLEnn1WaY9PggIy-KRkeqFjk&code_challenge_method=S256&state=wclCFyCFjm7HFvus9cmgNYdhZyuZc3QA5AnC0fyBrtw
set-cookie: OpenIddict.Client.State.u2gnDRQ75jUY6HD65-yQo0IadiJRxf81279HPFcNn1M=AQAAACtrR1BDMWg0SHctQ3pxdjhma1R0NFFzSWRCaUNYM0tHVXJrNC0wUDdjN2tN; expires=Fri, 08 Mar 2024 15:47:01 GMT; path=/; secure; samesite=none; httponly
content-length: 0
request-context: appId=cid-v1:919cbad0-6934-4760-a4d8-67dfb6823a80
... but it's not sent back by the browser during the callback phase:
GET https://localhost:7773/callback/login/local?code=y0wpQo766Gk_iJb88uMg9BMacaZy7qVOwdFJXnVfIT4&state=PrRdWemY5syo7pSdob5v7cSzduTAiKFLNllMyJGgcTc&iss=http%3A%2F%2Fhost.docker.internal%3A7774%2F HTTP/2
cache-control: max-age=0
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
sec-fetch-site: cross-site
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
referer: http://host.docker.internal:7774/
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
Host: localhost:7773
... hence the error you're seeing.
SSL/TLS termination is not an issue, but you need to configure your ASP.NET Core app correctly to ensure it's HTTPS-aware. See https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-8.0 for more information.
from openiddict-core.
Yes, I figured its related to the callback and redirect to the browser, how to configure that on the BFF? should it be configured as a server as well?
from openiddict-core.
The problem seems to only affect your authorization server app, not the BFF server that uses HTTPS (https://localhost:7773/).
from openiddict-core.
so the flow should be Browser -> BFF -> Auth (Login) -> Auth -> BFF -> Browser
or Browser -> BFF -> Auth (Login) -> Auth -> Browser
from openiddict-core.
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.All;
});
and
app.UseForwardedHeaders();
Are used on both BFF and Auth Server, do the APIs need it as well?
from openiddict-core.
so the flow should be
Browser -> BFF -> Auth (Login) -> Auth -> BFF -> Browser
orBrowser -> BFF -> Auth (Login) -> Auth -> Browser
The first one.
Are used on both BFF and Auth Server, do the APIs need it as well?
You might also need to configure the KnownProxies
/KnownNetworks
as shown in the docs (see also https://stackoverflow.com/questions/51143761/asp-net-core-docker-https-on-azure-app-service-containers).
If your APIs are also deployed as containerized apps, they may need the same treatment. That said, it should have no impact on the OIDC user flow, that doesn't involve the APIs at this stage.
from openiddict-core.
Trying to fix SSL made it worse, it stopped working, then adding a local CA, and making a certificate from it almost worked, but the BFF failed with PartialChain
, after adding HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
in the BFF and the API servers, it went back to the No correlation cookie...
error, but I can confirm its coming out of the BFF and not the Auth server.
.AuthServer | | 2024-03-10T05:43:57.553542586Z info: .AuthServer.Areas.Identity.Pages.Account.LoginModel[0]
.AuthServer | | 2024-03-10T05:43:57.553589787Z User logged in.
.AuthServer | | 2024-03-10T05:43:57.567226927Z info: OpenIddict.Server.OpenIddictServerDispatcher[0]
.AuthServer | | 2024-03-10T05:43:57.567278727Z The request URI matched a server endpoint: Authorization.
.AuthServer | | 2024-03-10T05:43:57.570072136Z info: OpenIddict.Server.OpenIddictServerDispatcher[0]
.AuthServer | | 2024-03-10T05:43:57.570136936Z The authorization request was successfully extracted: {
.AuthServer | | 2024-03-10T05:43:57.570147736Z "client_id": "64176522-c3a3-441d-beb8-689b2524b7c3",
.AuthServer | | 2024-03-10T05:43:57.570151036Z "redirect_uri": "https://localhost:8773/callback/login/local",
.AuthServer | | 2024-03-10T05:43:57.570153536Z "response_type": "code",
.AuthServer | | 2024-03-10T05:43:57.570156036Z "scope": "openid profile api workflow",
.AuthServer | | 2024-03-10T05:43:57.570158036Z "nonce": "uVbRppjsVoY8mg2Z2oTPF4UHYz36T9GV-L0h8MZsDzk",
.AuthServer | | 2024-03-10T05:43:57.570160036Z "code_challenge": "0IVJtP03xBNM-lNbfkh5TDol69yhx881ejiDfBTjE30",
.AuthServer | | 2024-03-10T05:43:57.570162236Z "code_challenge_method": "S256",
.AuthServer | | 2024-03-10T05:43:57.570164036Z "state": "VF9Z09IOQ1VDDCHCoi6gHXvWz-vPJM6v7jJMGJCNPF0"
.AuthServer | | 2024-03-10T05:43:57.570166336Z }.
.AuthServer | | 2024-03-10T05:43:58.457324083Z The authorization response was successfully returned to 'https://localhost:8773/callback/login/local' using the query response mode: {
.AuthServer | | 2024-03-10T05:43:58.457331183Z "code": "[redacted]",
.AuthServer | | 2024-03-10T05:43:58.457333683Z "state": "VF9Z09IOQ1VDDCHCoi6gHXvWz-vPJM6v7jJMGJCNPF0",
.AuthServer | | 2024-03-10T05:43:58.457335483Z "iss": "https://host.docker.internal:8775/"
.AuthServer | | 2024-03-10T05:43:58.457434084Z }.
.MainBFF | | 2024-03-10T05:43:58.477966441Z info: OpenIddict.Client.OpenIddictClientDispatcher[0]
.MainBFF | | 2024-03-10T05:43:58.478020841Z The redirection request was successfully extracted: {
.MainBFF | | 2024-03-10T05:43:58.478027341Z "code": "[redacted]",
.MainBFF | | 2024-03-10T05:43:58.478029641Z "state": "VF9Z09IOQ1VDDCHCoi6gHXvWz-vPJM6v7jJMGJCNPF0",
.MainBFF | | 2024-03-10T05:43:58.486287666Z "iss": "https://host.docker.internal:8775/"
.MainBFF | | 2024-03-10T05:43:58.486358466Z }.
.MainBFF | | 2024-03-10T05:43:59.093858179Z info: OpenIddict.Core.OpenIddictTokenManager[0]
.MainBFF | | 2024-03-10T05:43:59.093923479Z The token 'dd50cf65-9079-47c2-f3ab-08dc40c509ff' was successfully marked as redeemed.
.MainBFF | | 2024-03-10T05:43:59.107679420Z info: OpenIddict.Client.OpenIddictClientDispatcher[0]
.MainBFF | | 2024-03-10T05:43:59.107743520Z The response was successfully returned as a plain-text document: {
.MainBFF | | 2024-03-10T05:43:59.107750520Z "error": "invalid_request",
.MainBFF | | 2024-03-10T05:43:59.107753720Z "error_description": "No correlation cookie associated with the specified state can be found. Please try logging in again. If the error persists, please contact the website owner.",
.MainBFF | | 2024-03-10T05:43:59.107756720Z "error_uri": "https://documentation.openiddict.com/errors/ID2129"
.MainBFF | | 2024-03-10T05:43:59.107761120Z }.
from openiddict-core.
Hi @meywd Why deploy to Azure Container Apps? Why not just deploy to Azure App Services (Linux Plan) and you can avoid all the certificate setup problems
from openiddict-core.
This is local on docker
from openiddict-core.
@meywd can you please share a Fiddler trace with the new config in place?
from openiddict-core.
from openiddict-core.
Thanks. Looks like the cookie is still not correctly sent back. Two things:
- Check whether the cookie is correctly persisted using the browser tools.
- Try re-executing the login flow with the developer console of your browser open to see if there's anything relevant that would explain why it's not persisted or sent.
from openiddict-core.
could the double request be the reason?
from openiddict-core.
could this be the problem Expires: Thu, 01 Jan 1970 00:00:00 GMT
from openiddict-core.
No, it's the classical "delete cookies" stuff done by Identity when starting a new login process. It's done at the authorization server level and your issue is at the BFF level: it's unrelated.
Did you see anything in the console logs?
from openiddict-core.
from openiddict-core.
Check whether the cookie is correctly persisted using the browser tools.
Please check that too.
Have you tried with a different browser?
from openiddict-core.
yeah chrome and firefox
and no cookies
from openiddict-core.
and no cookies
Try starting a new authentication flow and see if there's a message logged when the OpenIddict correlation cookie is returned.
from openiddict-core.
just in case, here is the BFF Program.cs
var builder = WebApplication.CreateBuilder(args);
var config = builder.AddAzureAppConfig("MainBFF");
var certificateClient = builder.AddKeyVaultWithClient(config);
builder.AddOpenTelemetry(config);
builder.AddStorage(config);
builder.AddDataProtection(config);
var sqlConnectionString = config.GetConnectionString("SqlServer")!;
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
// Configure the context to use sqlite.
options.UseSqlServer(sqlConnectionString);
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict<Guid>();
});
builder.Services.AddAntiforgery(options =>
{
options.HeaderName = "X-XSRF-TOKEN";
options.Cookie.Name = "__Host-X-XSRF-TOKEN";
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
});
var enableDebugging = config.GetValue<bool>("EnableDebugging");
builder.Services.AddHttpClient();
builder.Services.AddOptions();
var openIDConnectSettings = config.GetSection("OpenIDConnectSettings");
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
options.ExpireTimeSpan = TimeSpan.FromMinutes(50);
options.SlidingExpiration = false;
});
// OpenIddict offers native integration with Quartz.NET to perform scheduled tasks
// (like pruning orphaned authorizations from the database) at regular intervals.
builder.Services.AddQuartz(options =>
{
options.UseSimpleTypeLoader();
options.UseInMemoryStore();
});
// Register the Quartz.NET service and configure it to block shutdown until jobs are complete.
builder.Services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
builder.Services
.AddOpenIddict()
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
// Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>()
.ReplaceDefaultEntities<Guid>();
// Enable Quartz.NET integration.
options.UseQuartz();
})
.AddClient(options =>
{
options
.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow()
.AllowClientCredentialsFlow();
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String(builder.Configuration["<key name>"]!)));
// Register the signing credentials.
var cert = new X509Certificate2(certificateClient.DownloadCertificate("<cert name>"));
options.AddSigningCertificate(cert);
// Register the ASP.NET Core host and configure the ASP.NET Core-specific options.
options.UseAspNetCore()
.EnableStatusCodePagesIntegration()
.EnableRedirectionEndpointPassthrough()
.EnablePostLogoutRedirectionEndpointPassthrough();
// Register the System.Net.Http integration and use the identity of the current
// assembly as a more specific user agent, which can be useful when dealing with
// providers that use the user agent as a way to throttle requests (e.g Reddit).
options.UseSystemNetHttp()
.ConfigureHttpClientHandler(handler =>
{
if(builder.Environment.IsDevelopment())
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
})
.SetProductInformation(typeof(Program).Assembly);
// Add a client registration matching the client application definition in the server project.
var registration = new OpenIddictClientRegistration
{
Issuer = new Uri(openIDConnectSettings["Authority"]!, UriKind.Absolute),
ClientId = openIDConnectSettings["ClientId"],
ClientSecret = openIDConnectSettings["ClientSecret"],
// Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint
// URI per provider, unless all the registered providers support returning a special "iss"
// parameter containing their URL as part of authorization responses. For more information,
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4.
RedirectUri = new Uri("callback/login/local", UriKind.Relative),
PostLogoutRedirectUri = new Uri("callback/logout/local", UriKind.Relative)
};
registration.Scopes.UnionWith((openIDConnectSettings["Scope"] ?? "").Split(" ", StringSplitOptions.RemoveEmptyEntries).Select(s => s)!);
options.AddRegistration(registration);
});
builder.Services.AddControllersWithViews(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
builder.Services.AddRazorPages();
// Create an authorization policy used by YARP when forwarding requests
// from the WASM application to the Dantooine.Api1 resource server.
builder.Services.AddAuthorization(options => options.AddPolicy("CookieAuthenticationPolicy", builder =>
{
builder.AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme);
builder.RequireAuthenticatedUser();
}));
var cert = new X509Certificate2(await certificateClient.DownloadCertificateAsync("<cert name>"));
builder.Services.AddReverseProxy()
.LoadFromConfig(config.GetSection("ReverseProxy"))
.ConfigureHttpClient((context, handler) =>
{
handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
return true;
},
ClientCertificates = new X509CertificateCollection
{
cert
}
};
})
.AddTransforms(builder => builder.AddRequestTransform(async context =>
{
// Attach the access token retrieved from the authentication cookie.
//
// Note: in a real world application, the expiration date of the access token
// should be checked before sending a request to avoid getting a 401 response.
// Once expired, a new access token could be retrieved using the OAuth 2.0
// refresh token grant (which could be done transparently).
var token = await context.HttpContext.GetTokenAsync(
scheme: CookieAuthenticationDefaults.AuthenticationScheme,
tokenName: Tokens.BackchannelAccessToken);
context.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue(Schemes.Bearer, token);
}));
builder.WebHost.UseWebRoot("wwwroot");
builder.WebHost.UseStaticWebAssets();
// Add builder.Services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.All;
});
// Configure CORS to allow designer app hosted on a different origin to invoke the APIs.
builder.Services.AddCors(cors => cors
.AddDefaultPolicy(policy => policy
.AllowAnyOrigin() // For demo purposes only. Use a specific origin instead.
.AllowAnyHeader()
.AllowAnyMethod()));
// Register the worker responsible for creating the database used to store tokens.
// Note: in a real world application, this step should be part of a setup script.
builder.Services.AddHostedService<Worker>();
var app = builder.Build();
app.UseForwardedHeaders();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors();
//app.UseSecurityHeaders(
// SecurityHeadersDefinitions.GetHeaderPolicyCollection(app.Environment.IsDevelopment(),
// config["OpenIDConnectSettings:Authority"]!));
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.MapReverseProxy();
app.MapFallbackToPage("/_Host");
app.Run();
from openiddict-core.
and no cookies
Try starting a new authentication flow and see if there's a message logged when the OpenIddict correlation cookie is returned.
not seeing any messages, could the use of host.docker.internal
instead of localhost cause an issue?
from openiddict-core.
no seeing any messages, could the use of
host.docker.internal
instead of localhost cause an issue?
It shouldn't.
Unfortunately, I'm out of ideas at this point. I'd need to debug that myself: consider sharing your entire solution (Docker stuff included) and I'll try to repro the issue locally.
from openiddict-core.
Does the use of AddDataProtection
cause issues?
builder.Services
.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri(config.GetSection("DataProtection").GetValue<string>("Url")!))
.UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
if the keys for each server are different, do they need to share the same key ring?
from openiddict-core.
No, DP configuration would only be a concern if you had multiple instances running.
Here, it's a server-browser (bad) cookie interaction. A lot harder to debug...
from openiddict-core.
checking the token data, anything odd here?
from openiddict-core.
No. If the state token was invalid, you'd get a different issue. It's really a cookie issue here.
from openiddict-core.
on a side note, how does the BFF know where to redirect?
from what I see, the return URL is the API URL, so UI app requests API through BFF, BFF does login then returns to the API URL.
ui.domain.com/admin/company -> bff.domain.com/admin/company -> auth.domain.com/authorize -> auth.domain.com/login -> bff.domain.com/callback/login -> then what happens?
from openiddict-core.
Currently the BFF is simply a client, does it need to be a client and a server so it can redirect back to the UI, and the UI is registered as a client to the BFF?
from openiddict-core.
on a side note, how does the BFF know where to redirect?
That ReturnUrl
is eventually preserved in the state token and can be restored from your AuthenticationController
.
ui.domain.com/admin/company -> bff.domain.com/admin/company -> auth.domain.com/authorize -> auth.domain.com/login -> bff.domain.com/callback/login -> then what happens?
You're redirected back to the initial page.
Note: the SPA (what you call UI?) and the BFF must be on the same domain for things to work correctly, otherwise cookies won't be shared between the SPA and the BFF.
from openiddict-core.
they are two separate apps hosted on different subdomains, so it seem I need a gateway to redirect calls.
from openiddict-core.
The standard approach is to have a BFF per SPA. Thatโs the whole point.
from openiddict-core.
If it's for API optimization yes, but for auth purposes why do you need one per one, couldn't one BFF serve multiple SPAs?
from openiddict-core.
The unique raison dโรชtre of a BFF is to act as a proxy between the SPA and the OIDC server. In practice, itโs almost always the app that serves the SPA that also acts as the BFF.
(BTW, itโs called backend-for-frontend, not backend-for-frontends ๐)
from openiddict-core.
Could this be related to correlation cookie error?
from openiddict-core.
Possibly.
As I said, I need to test the whole thing locally to be able to help you more. Otherwise, we're just going to spend a lot of time trying to guess what may or may not cause this issue.
from openiddict-core.
I understand, I appreciate your help, I need to clean it before I can send it.
I noticed that the auth server requests login, although it says I am logged in and it displays my user name.
from openiddict-core.
Spent all yesterday stripping the code down to the basics but couldn't get it to work somehow, then now I got the idea to try the same pattern on your Dantooine sample, so I add allow all CORS call
// Configure CORS to allow designer app hosted on a different origin to invoke the APIs.
services.AddCors(cors => cors
.AddDefaultPolicy(policy => policy
.AllowAnyOrigin() // For demo purposes only. Use a specific origin instead.
.AllowAnyHeader()
.AllowAnyMethod()));
to both Auth and BFF servers and called the BFF from the UI, the same error showed.
No correlation cookie associated with the specified state can be found.
so the issue here is that the original call is not coming from the BFF...
from openiddict-core.
so the issue here is that the original call is not coming from the BFF...
What do you mean exactly?
FWIW, I tried to reproduce it locally and wasn't able to (even when hosting the BFF and the WASM app on a separate domain).
That said, you don't need CORS at all in a BFF scenario, since everything shares the same origin/domain (that's even the whole point, otherwise cookies couldn't be shared between the SPA and its BFF), so if it's causing issues, just remove it?
from openiddict-core.
I am testing locally, my SPA is not served from the BFF, its hosted on its own service and port, so it can't access the BFF, and when i added allow all to the BFF it complained about the auth server rejecting the request, so I added allow all there.
from openiddict-core.
you mentioned sharing cookies across domain, in production all will be hosted in separate sub-domains of the same domain, so it should work correct?
from openiddict-core.
you mentioned sharing cookies across domain, in production all will be hosted in separate sub-domains of the same domain, so it should work correct?
By default, cookies are not shared with subdomains. See https://stackoverflow.com/questions/18492576/share-cookies-between-subdomain-and-domain for more information.
I am testing locally, my SPA is not served from the BFF, its hosted on its own service and port, so it can't access the BFF, and when i added allow all to the BFF it complained about the auth server rejecting the request, so I added allow all there.
Most likely the root cause of this issue...
I really feel like you're trying to use the BFF pattern incorrectly... ๐
from openiddict-core.
I really feel like you're trying to use the BFF pattern incorrectly... ๐
that is mostly correct as its my first time doing it, my idea is that I don't like mixing back-end and front-end, I thought we are done with AJAX\MVC style projects, seems not, its just cleaner to split them for development.
The whole idea is doing SSO, multiple APIs, multiple SPAs(some end users, some internal\admin users) with one or more BFFs to secure them, plus potential 3rd party websites connecting to the APIs using App to App auth, 3rd party and 1st party mobile apps.
the reason why I think it should work separately, is because BFFs for mobile can't actually serve the mobile apps them selves, they are deployed through stores, but my understanding could be wrong.
By default, cookies are not shared with subdomains. See https://stackoverflow.com/questions/18492576/share-cookies-between-subdomain-and-domain for more information.
So can we do this?
from openiddict-core.
the reason why I think it should work separately, is because BFFs for mobile can't actually serve the mobile apps them selves, they are deployed through stores, but my understanding could be wrong.
"BFFs for mobile apps" don't exist: mobile apps can directly use OIDC/token authentication without requiring a cookie/token translation mechanism (which is what a BFF is, essentially). A BFF only makes sense for a SPA.
So can we do this?
I don't think I'd recommend it, but you should technically be able to do it. You'll need to tweak the cookie options of the Identity cookie handlers and of the OpenIddict client (https://github.com/openiddict/openiddict-core/blob/dev/src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreOptions.cs#L77) to specify an explicit domain, tho'.
from openiddict-core.
Related Issues (20)
- SPA and BFF on different sub-domains, BFFs for mobile apps HOT 6
- Getting The security token is missing during login validation on postman client authorization or web client authorization HOT 2
- InvalidOperationException: Cannot redirect to the authorization endpoint, the configuration may be missing or invalid. HOT 7
- OpenIddict + SPA UI Question HOT 9
- Remove `Uri.IsWellFormedOriginalString()`/`Uri.IsWellFormedUriString()`
- The specified token is invalid since we renewed SSL certificate in Azure key vault HOT 14
- invalid_token returned by authorization callback HOT 14
- Claims not found in token of external provider (Microsoft) HOT 5
- Using KeyVaultSecurityKey as asymmetric signing key and/or symmetric encryption key HOT 6
- unauthorized_client when changing url HOT 6
- Using "role" claims from external providers in access tokens HOT 7
- Update the OpenIddict client ASP.NET Core/OWIN integrations to support overriding the requested scopes via `AuthenticationProperties`
- openiddict 5.0.1 => 5.1.0, breaking change when adding amr array claim to id_token HOT 5
- Sharing the same signing key in a multi tenant environment HOT 7
- Enable the use of Azure Workload Identities with `.AddClient(options => { options.UseWebProviders().AddMicrosoft...})` HOT 3
- Microsoft Entra: ResponseMode "query" is not working good HOT 12
- Use TimeProvider HOT 3
- Empty string reading Httpcontext body from x-www-form-urlencoded POST HOT 4
- Revoked token is still valid for `UseLocalServer()` configuration HOT 4
- Calling AuthenticateInteractivelyAsync from api server in windows installed app HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from openiddict-core.