You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OpenIddict and TokenValidation in an OC module (Feature): how to configure it? And why the ContentManager always return a null Author and Owner?
#16950
We have partially discussed this topic here, but now that we have identified the problem in the authentication procedure, we want to open this new thread as the previous one has become too large.
In short, we are experiencing an issue with the Token Validation inside our Orchard Core 1.8.2 module (Feature). We are working on developing a Chat microservice, and we have an OC module (Feature) utilizing SignalR where we are attempting to implement "Token Validation". Our JWT token is provided by our SSO microservice, which is built using OpenIddict and Orchard Core 1.8.2.
Something is going wrong because whenever we try to create our Content Items using the ContentManager, we always get a null Author and a null Owner. Below you can see a screenshot. Instead, running the Chat microservice in localhost, if no one log into the backoffice, the ContentManager fail to instantiate a new content item with the error: System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name'. This happens at this line of the OC code, because contentTypeDefinition is null, even though the content type exists.
Screenshot of ContentManager, where Author and Owner are null:
We suspect there’s an issue with our JWT configuration or in the Startup.cs of our OC module.
Could it be that the Audience is set incorrectly? In the generated JWT, we are seeing oct:Default (we have only one tenant), or could it be something else? We're at our wit's end trying to solve this 🫤
Maybe @kevinchalet, since you are the creator of OpenIddict ☺️, you have an easy answer for us?
Thank you so much!
Here some of our code we mentioned above
Here the Startup.cs:
usingBookstore.Module.SignalR.OurHub;usingMicrosoft.AspNetCore.Builder;usingMicrosoft.AspNetCore.Hosting;usingMicrosoft.Extensions.DependencyInjection;usingMicrosoft.IdentityModel.Tokens;namespaceBookstore.Module.SignalR{publicclassStartup:StartupBase{publicoverridevoidConfigureServices(IServiceCollectionservices){services.AddAuthentication().AddJwtBearer("ChatHub", options =>{// Configure validation Authorityoptions.Authority="http://host.docker.internal:12103/";// URL OpenIddict serveroptions.Audience="oct:Default";// Orchard Core Tenant Default audience (as shown in the JWT token)options.RequireHttpsMetadata=false;// TODO: Remove for production// Configure token validationoptions.TokenValidationParameters=newTokenValidationParameters{ValidateIssuer=true,ValidateAudience=true,ValidateLifetime=true};});// Register SignalR services in Orchard Coreservices.AddSignalR();}publicoverridevoidConfigure(IApplicationBuilderapp){// Use endpoint routing to map the SignalR hubsapp.UseEndpoints(endpoints =>{// Map the SignalR hub for chatendpoints.MapHub<ChatHub>("/chathub");});}}}
Here the ChatHub.cs (this class is inside our OC module, the IChatHandler instead is in the Chat Microservice). On top of this class there's our custom "ChatHub" API attribute: [Authorize(AuthenticationSchemes = "ChatHub"), IgnoreAntiforgeryToken]:
usingMicrosoft.AspNetCore.SignalR;usingBookstore.Common.Abstractions;usingMicrosoft.AspNetCore.Authorization;usingMicrosoft.AspNetCore.Mvc;usingMicrosoft.Extensions.Logging;usingBookstore.Common.Models.Api.Microservices.Chat;usingSystem.Net;usingBookstore.Common.Models;namespaceBookstore.Module.SignalR.OurHub{[Authorize(AuthenticationSchemes="ChatHub"),IgnoreAntiforgeryToken]publicclassChatHub:Hub{privatereadonlyIChatHandler_chatHandler;privatereadonlyILogger<ChatHub>_logger;publicChatHub(IChatHandlerchatHandler,ILogger<ChatHub>logger){_chatHandler=chatHandler;_logger=logger;}// This method is the ONLY ONE called by the client after the first connection, where is also called OnConnectedAsync()publicasyncTaskSendMessageToRoom(stringroomName,stringuserAId,stringuserAName,stringuserBId,stringuserBName,stringmessage){_logger.LogInformation($"{nameof(ChatHub)}-{nameof(SendMessageToRoom)} started for room: {roomName}");// Step 1: Check if the chat room existsApiResult<List<ChatMessageApiModel>>roomResult=await_chatHandler.GetMessagesForRoomAsync(roomName,userAId,userBId);if(roomResult.StatusCode==HttpStatusCode.NotFound){_logger.LogWarning($"Room {roomName} does not exist. Creating a new chat room.");// Create a new chat room if it doesn't existvarnewChatRoomApiModel=newChatRoomApiModel{RoomName=roomName,UserAId=userAId,UserAName=userAName,UserBId=userBId,UserBName=userBName,};varcreateRoomResult=await_chatHandler.CreateChatRoomAsync(newChatRoomApiModel);if(createRoomResult.StatusCode!=HttpStatusCode.OK){_logger.LogError($"Failed to create room {roomName}.");awaitClients.Caller.SendAsync("ErrorMessage","Failed to create chat room.");return;}_logger.LogInformation($"Room {roomName} successfully created.");}// Step 2: Create a ChatMessageApiModel object with message detailsvarchatMessageApiModel=newChatMessageApiModel{UserName=userAName,// Name of the user sending the messageMessage=message};// Step 3: Save the message using the ChatHandlervarsaveMessageResult=await_chatHandler.SaveMessageAsync(roomName,userAId,userAName,userBId,userBName,chatMessageApiModel);// Step 4: Check if the message was successfully savedif(saveMessageResult.StatusCode==HttpStatusCode.OK){// Send the message to all clients in the group (room)awaitClients.Group(roomName).SendAsync("ReceiveMessage",userAName,message);}else{// Handle errors, such as logging or notifying the clientawaitClients.Caller.SendAsync("ErrorMessage","Failed to send the message.");}}publicoverrideasyncTaskOnConnectedAsync(){varroomName=Context.GetHttpContext().Request.Query["room"];varuserAId=Context.GetHttpContext().Request.Query["userAId"];varuserBId=Context.GetHttpContext().Request.Query["userBId"];varuserAName=Context.GetHttpContext().Request.Query["userAName"];varuserBName=Context.GetHttpContext().Request.Query["userBName"];if(string.IsNullOrWhiteSpace(roomName)||string.IsNullOrWhiteSpace(userAId)||string.IsNullOrWhiteSpace(userBId)||string.IsNullOrWhiteSpace(userAName)||string.IsNullOrWhiteSpace(userBName)){stringerrorMessage=$"Missing required parameters. Room: {roomName}, userAId: {userAId}, userBId: {userBId}, userAName: {userAName}, userBName: {userBName}.";_logger.LogError(errorMessage);awaitClients.Caller.SendAsync("ErrorMessage",errorMessage);return;}// Check if userAId and userBId are the sameif(userAId==userBId){stringerrorMessage=$"userAId: \"{userAId}\" and userBId: \"{userBId}\" cannot be the same!";_logger.LogError(errorMessage);awaitClients.Caller.SendAsync("ErrorMessage",errorMessage);return;}_logger.LogInformation($"User connected to room {roomName}, UserAId: {userAId}, UserBId: {userBId}.");// Step 1: Add the user to the room groupawaitGroups.AddToGroupAsync(Context.ConnectionId,roomName);// Step 2: Check if the chat room exists; if not, create a new oneApiResult<List<ChatMessageApiModel>>roomResult=await_chatHandler.GetMessagesForRoomAsync(roomName,userAId,userBId);if(roomResult.StatusCode==HttpStatusCode.NotFound){_logger.LogWarning($"Room {roomName} does not exist. Creating a new chat room.");varnewChatRoomApiModel=newChatRoomApiModel{RoomName=roomName,UserAId=userAId,UserAName=userAName,UserBId=userBId,UserBName=userBName,};varcreateRoomResult=await_chatHandler.CreateChatRoomAsync(newChatRoomApiModel);if(createRoomResult.StatusCode!=HttpStatusCode.OK){_logger.LogError($"Failed to create room {roomName}.");awaitClients.Caller.SendAsync("ErrorMessage","Failed to create chat room.");return;}_logger.LogInformation($"Room {roomName} successfully created.");}else{// Step 3: If room exists, send previous messages to the clientforeach(varmessageinroomResult.Data){awaitClients.Caller.SendAsync("ReceiveMessage",message.UserName,message.Message);}}awaitbase.OnConnectedAsync();}}}
Our JWT token decoded, released by our OpenIddict SSO:
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi everyone,
We have partially discussed this topic here, but now that we have identified the problem in the authentication procedure, we want to open this new thread as the previous one has become too large.
In short, we are experiencing an issue with the
Token Validation
inside our Orchard Core 1.8.2 module (Feature). We are working on developing a Chat microservice, and we have an OC module (Feature) utilizing SignalR where we are attempting to implement "Token Validation". Our JWT token is provided by our SSO microservice, which is built using OpenIddict and Orchard Core 1.8.2.Something is going wrong because whenever we try to create our Content Items using the
ContentManager
, we always get a nullAuthor
and a nullOwner
. Below you can see a screenshot.Instead, running the Chat microservice in localhost, if no one log into the backoffice, the ContentManager fail to instantiate a new content item with the error:
System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name'
. This happens at this line of the OC code, becausecontentTypeDefinition
is null, even though the content type exists.Screenshot of
ContentManager
, whereAuthor
andOwner
are null:We suspect there’s an issue with our JWT configuration or in the Startup.cs of our OC module.
Audience
is set incorrectly? In the generated JWT, we are seeingoct:Default
(we have only one tenant), or could it be something else? We're at our wit's end trying to solve this 🫤Maybe @kevinchalet, since you are the creator of OpenIddict☺️ , you have an easy answer for us?
Thank you so much!
Here some of our code we mentioned above
Here the
Startup.cs
:Here the
ChatHub.cs
(this class is inside our OC module, theIChatHandler
instead is in the Chat Microservice). On top of this class there's our custom "ChatHub" API attribute:[Authorize(AuthenticationSchemes = "ChatHub"), IgnoreAntiforgeryToken]
:Our
JWT token decoded
, released by our OpenIddict SSO:Beta Was this translation helpful? Give feedback.
All reactions