Closed mohaaron closed 8 months ago
I think you are passing ‘Access-Control-Allow-Origin’
header with value "*"
. If you allow credentials on your API I dont think you can pass ‘Access-Control-Allow-Origin’
with value "*". You are saying that you allow anyone to come in but also allow credentials.
Either remove allow credentials from server or remove ‘Access-Control-Allow-Origin’
value on the request.
I think you are passing
‘Access-Control-Allow-Origin’
header with value"*"
. If you allow credentials on your API I dont think you can pass‘Access-Control-Allow-Origin’
with value "*". You are saying that you allow anyone to come in but also allow credentials. Either remove allow credentials from server or remove‘Access-Control-Allow-Origin’
value on the request.
I don't understand your answer. The I don't have control over this API as it's a Duende test site. I am successfully logging in to the test site and then trying to call the API test address using the credentials that were created during the login.
I just tried the following but this seems to not pass a token in the request and I get a 401 response. I've updated the repo to use this CookieHandler instead of the AuthorizationMessageHandler. My goal here is to understand how to pass the token in HttpClient requests to the remote API server which in this case is Duende's demo server.
public class CookieHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
request.SetBrowserRequestMode(BrowserRequestMode.NoCors);
return await base.SendAsync(request, cancellationToken);
}
}
I think you are passing
‘Access-Control-Allow-Origin’
header with value"*"
. If you allow credentials on your API I dont think you can pass‘Access-Control-Allow-Origin’
with value "*". You are saying that you allow anyone to come in but also allow credentials. Either remove allow credentials from server or remove‘Access-Control-Allow-Origin’
value on the request.I don't understand your answer. The I don't have control over this API as it's a Duende test site. I am successfully logging in to the test site and then trying to call the API test address using the credentials that were created during the login.
I just tried the following but this seems to not pass a token in the request and I get a 401 response. I've updated the repo to use this CookieHandler instead of the AuthorizationMessageHandler. My goal here is to understand how to pass the token in HttpClient requests to the remote API server which in this case is Duende's demo server.
public class CookieHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); request.SetBrowserRequestMode(BrowserRequestMode.NoCors); return await base.SendAsync(request, cancellationToken); } }
Are you trying to pass token in the cookie or in authorization header?
I am trying to understand if you are trying to authenticate via cookie or Bearer Token?
I am assuming you are trying to call REST API via HttpClient
and trying to pass same credentials you via cookie or Authorization Header.
HttpClient
will not automatically append access cookie or token, you have to manually include cookie into cookie container
or include your Bearer token in Authorization header.
@mohaaron did you try using our sample here: https://github.com/DuendeSoftware/Duende.AccessTokenManagement/tree/main/samples/BlazorServer?
Does that sample work for you unchanged?
Can you highlight what is different about your sample please?
@josephdecock Thank you for the response.
I originally pulled down that example sample and it's what I started with. I added a new Blazor WebApp project to the solution that uses Interactive Auto mode. I copied what I needed to from the Blazor server project into the SSR side of the web app. As you can see in the repo sample that I provided the SSR side works correctly and routes the request to the demo site for login. Once logged in the demo site redirects back to the app. This is all good and being done on the server side of things. the entire app is being authenticated correctly.
Now the difference is in the fact that the auto render mode runs as WASM after the initial load. When this happens the authentication token needs to be passed up to the demo API endpoint which is where things go wrong. I'm getting a CORS error back from the demo API endpoint that is used in the Blazor Server sample. I'm guessing this is happening due to the HttpClient being used to make the call.
Have you looked at the sample I provided?
Maybe the issue is that I'm trying to use the CookieHandler when I should be using the CustomAuthorizationMessageHandler. Only problem is that I keep getting a dependency injection error saying that IAccessTokenProvider is not in DI. I have an open issue in the aspnet Github repository about this which has no answer yet. https://github.com/dotnet/aspnetcore/issues/53066
Any help would be greatly appreciated. I think I'm not the only one trying to figure out how to do this with the new WebApp template.
Thanks for clarifying. The new automatic modes in blazor 8 are a really big change, and supporting it well is a problem that we are actively working on.
Blazor server, blazor wasm, and server side rendering (SSR) have fundamentally different security models.
In blazor server, you have a server side component streaming updates over a web socket. There are no http requests sent during that streaming, so you have no cookies to work with. This means that you need a server side store of tokens, and you need the server to manage tokens, store them in the server side token store, and make api calls.
In blazor wasm, you have the UI running in the browser. Just as with a more "traditional" (non-wasm) SPA, our advice is to use the BFF pattern with blazor wasm. This means that the UI will make HTTP requests secured with a cookie to the BFF, and then the BFF will manage tokens for the session and proxy API calls for the UI.
Finally in blazor ssr, there is an http request authenticated with a cookie and then server side code runs to create an http response.
The interactive render modes cause multiple of these code paths to be needed. InteractiveServer and InteractiveWasm both do an initial SSR before switching to server and wasm mode respectively, while interactive auto does SSR and then switches between server and wasm as the wasm resources load.
To sum up, sometimes the code runs in the browser and you need a BFF, and sometimes the code runs in the server and you don't need a BFF.
One way to achieve this is to have an interface that describes the data access you need, and then implement it two ways (one calling the bff and one not). Then you register the bff based implementation in the client project and the direct access in the server project. The downside of this is that it is rather complex to implement, and we'd really like to improve the dev experience when working with this kind of architecture. This is an area of active development and experimentation for us, so stay tuned!
In the interest of keeping things organized, I'm closing this along with some other related issues, but feel free to provide feedback and comments in (https://github.com/DuendeSoftware/Samples/issues/142)
Which version of Duende IdentityServer are you using? Demo Server
Which version of .NET are you using? 8.0.100
Describe the bug Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at ‘https://demo.duendesoftware.com/api/test’. (Reason: Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’).
A clear and concise description of what the bug is.
To Reproduce
I created this sample from a Blazor Server sample provided by Duende. I have a sample Github repo here: https://github.com/mohaaron/CustomAuthorizationHandler
Steps to reproduce the behavior.
Pull Github repo Run WebApp project Login to the demo identity server Navigate to the Fetch Remote Data menu item
A clear and concise description of what you expected to happen.
Log output/exception with stacktrace
Additional context
Add any other context about the problem here.