4

I using SignalR in my Blazor server app. I added services.AddSignalR() in startup.cs file. Then I can't take token. Because http context is null. Then I removed services.AddSignalR() from startup.cs file. it is normal working. Then i can take token from http client. How to solve it?

Thank you.

Startup.cs file:

services
    .AddAuthentication(options =>
    {
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = identityUrl.ToString();
        options.SignedOutRedirectUri = callBackUrl.ToString();
        options.ClientId = useLoadTest ? "mvctest" : "blazor";
        options.ClientSecret = "secret";
        options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
        options.SaveTokens = true;
        options.GetClaimsFromUserInfoEndpoint = true;
        options.RequireHttpsMetadata = false;
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("post");
        options.Scope.Add("family");
        options.Scope.Add("webpostagg");

    });

services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddSignalR();

services.AddHttpClient<IPostService, PostService>()                  
    .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();

HttpClientAuthorizationDelegatingHandler.cs:

public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)

{
    _httpContextAccesor = httpContextAccesor;
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    string authorizationHeader;
    if (_httpContextAccesor.HttpContext == null)
    {
        authorizationHeader = string.Empty;
    }
    else
    {
        authorizationHeader = _httpContextAccesor.HttpContext
        .Request.Headers["Authorization"];
    }

    if (!string.IsNullOrEmpty(authorizationHeader))
    {
        request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
    }

    var token = await GetToken();

    if (token != null)
    {
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }

    return await base.SendAsync(request, cancellationToken);
}

public async Task<string> GetToken()
{
    const string ACCESS_TOKEN = "access_token";

    return await _httpContextAccesor.HttpContext
        .GetTokenAsync(ACCESS_TOKEN);
}
itminus
  • 23,772
  • 2
  • 53
  • 88
batbayar
  • 83
  • 8
  • I tried your code, but it works fine for me. Could you please show us how the `IPostService` is invoked? – itminus Feb 27 '20 at 04:31
  • I added following code to startup.cs file. And it's working. – batbayar Feb 27 '20 at 05:58
  • options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }; options.Events = new OpenIdConnectEvents { OnAccessDenied = context => { context.HandleResponse(); context.Response.Redirect("/"); return Task.CompletedTask; } }; – batbayar Feb 27 '20 at 05:59
  • I just to deploy kubernetes. And this url is don't working (_hubConnection = new HubConnectionBuilder() .WithUrl("http://beta.ugiinbichig.mn/socialhub") .Build();) What do you think about it? – batbayar Feb 27 '20 at 06:01
  • I think you need to specify the scheme : `http://...` or `https://...` – itminus Feb 27 '20 at 06:13
  • i using http : // beta.ugiinbichig.mn/socialhub – batbayar Feb 27 '20 at 06:16
  • Could you please show us the error exceptions/logs? – itminus Feb 27 '20 at 06:19
  • JsonReaderException: '<' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0. System.Text.Json.ThrowHelper.ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte, ReadOnlySpan bytes) – batbayar Feb 27 '20 at 06:22
  • InvalidDataException: Invalid negotiation response received. Microsoft.AspNetCore.Http.Connections.NegotiateProtocol.ParseResponse(ReadOnlySpan content) – batbayar Feb 27 '20 at 06:22
  • There's something wrong with the request. Where did you get the `'<' is an invalid start of a value. LineNumber: 0 | B`? The server should returns a JSON. But it seems returns a HTML? – itminus Feb 27 '20 at 06:41
  • i changed url http : // 23.101.19.81/posthub. it is normal working. socialhub and posthub is same. 23.101.19.81 is asp.net core mvc app. beta.ugiinbichig.mn is blazor app. – batbayar Feb 27 '20 at 06:47
  • I checked using break point. And don't working hubconnection.StartAsync(). i think url is unknown. what do you think about hubconnection.withUrl? – batbayar Feb 27 '20 at 06:55
  • I'm really confused. Is there a minimal demo that reproduces the same issue? – itminus Feb 27 '20 at 06:58
  • i don't have any demo. what do you think about subdomain? is it okey? – batbayar Feb 27 '20 at 07:03
  • 1
    i just changed _hubConnection = new HubConnectionBuilder() .WithUrl("http : //23.101.19.81/posthub") .Build();. it is working. – batbayar Feb 27 '20 at 07:08
  • @itminus I found my mistake :). Thank you for your help. – batbayar Feb 27 '20 at 09:22

1 Answers1

2

Please, do not use HttpContext in Server Blazor App. It is not available. Server-side Blazor is WebSocket-based, not HTTP requests based. Just don't do that.

Here are links to my answer how to implement OpenID Connect, and others, where you'll find answers to your questions.

See these: how to jwt authentication blazor server without microsoft identity? How do I get the access token from a blazor (server-side) web app? How to add OpenIdConnect via IdentityServer4 to ASP.NET Core ServerSide Blazor web app? How to get JWT authenticated sign-in user from identity claims in asp.net web api How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent Blazor Adding HttpClientHandler to add Jwt to HTTP Header on requests

Blazor: Redirect to Login page when there is no session / JWT token?

Note: There are more answers related to Jwt,OpenID Connect, etc. You just have to look for them

Community
  • 1
  • 1
enet
  • 41,195
  • 5
  • 76
  • 113