CoreWCF / CoreWCF

Main repository for the Core WCF project
MIT License
1.66k stars 292 forks source link

Custom Username Password validation does not work #847

Closed ssmsam12345 closed 1 year ago

ssmsam12345 commented 2 years ago

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. CoreWCF.Security.MessageSecurityException: Cannot find a token authenticator for the 'CoreWCF.IdentityModel.Tokens.UserNameSecurityToken' token type. Tokens of that type cannot be accepted according to current security settings. at CoreWCF.Security.ReceiveSecurityHeader.ReadTokenAsync(XmlReader reader, SecurityTokenResolver tokenResolver, IList1 allowedTokenAuthenticators) at CoreWCF.Security.ReceiveSecurityHeader.ReadTokenAsync(XmlDictionaryReader reader, Int32 position, Byte[] decryptedBuffer, SecurityToken encryptionToken, String idInEncryptedForm, TimeSpan timeout) at CoreWCF.Security.ReceiveSecurityHeader.ExecuteReadingPassAsync(XmlDictionaryReader reader) at CoreWCF.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPassesAsync(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader) at CoreWCF.Security.ReceiveSecurityHeader.ProcessAsync(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy) at CoreWCF.Security.TransportSecurityProtocol.VerifyIncomingMessageCoreAsync(Message message, TimeSpan timeout) at CoreWCF.Security.TransportSecurityProtocol.VerifyIncomingMessageAsync(Message message, TimeSpan timeout) at CoreWCF.Security.SecurityProtocol.VerifyIncomingMessageAsync(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates) at CoreWCF.Dispatcher.ServerSecurityChannelDispatcher1.VerifyIncomingMessageAsync(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationState) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.ProcessReceivedRequestAsync(RequestContext requestContext) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.ProcessReceivedRequestAsync(RequestContext requestContext) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.DispatchAsync(RequestContext context) at CoreWCF.Channels.AspNetCoreReplyChannel.HandleRequestCore(HttpContext context) at CoreWCF.Channels.AspNetCoreReplyChannel.HandleRequest(HttpContext context) at CoreWCF.Channels.RequestDelegateHandler.HandleRequest(HttpContext context) at CoreWCF.Channels.ServiceModelHttpMiddleware.InvokeAsync(HttpContext context) at CoreWCF.Channels.MetadataMiddleware.InvokeAsync(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request. CoreWCF.Security.MessageSecurityException: Cannot find a token authenticator for the 'CoreWCF.IdentityModel.Tokens.UserNameSecurityToken' token type. Tokens of that type cannot be accepted according to current security settings. at CoreWCF.Security.ReceiveSecurityHeader.ReadTokenAsync(XmlReader reader, SecurityTokenResolver tokenResolver, IList1 allowedTokenAuthenticators) at CoreWCF.Security.ReceiveSecurityHeader.ReadTokenAsync(XmlDictionaryReader reader, Int32 position, Byte[] decryptedBuffer, SecurityToken encryptionToken, String idInEncryptedForm, TimeSpan timeout) at CoreWCF.Security.ReceiveSecurityHeader.ExecuteReadingPassAsync(XmlDictionaryReader reader) at CoreWCF.Security.LaxModeSecurityHeaderElementInferenceEngine.ExecuteProcessingPassesAsync(ReceiveSecurityHeader securityHeader, XmlDictionaryReader reader) at CoreWCF.Security.ReceiveSecurityHeader.ProcessAsync(TimeSpan timeout, ChannelBinding channelBinding, ExtendedProtectionPolicy extendedProtectionPolicy) at CoreWCF.Security.TransportSecurityProtocol.VerifyIncomingMessageCoreAsync(Message message, TimeSpan timeout) at CoreWCF.Security.TransportSecurityProtocol.VerifyIncomingMessageAsync(Message message, TimeSpan timeout) at CoreWCF.Security.SecurityProtocol.VerifyIncomingMessageAsync(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates) at CoreWCF.Dispatcher.ServerSecurityChannelDispatcher1.VerifyIncomingMessageAsync(Message message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationState) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.ProcessReceivedRequestAsync(RequestContext requestContext) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.ProcessReceivedRequestAsync(RequestContext requestContext) at CoreWCF.Dispatcher.SecurityReplyChannelDispatcher.DispatchAsync(RequestContext context) at CoreWCF.Channels.AspNetCoreReplyChannel.HandleRequestCore(HttpContext context) at CoreWCF.Channels.AspNetCoreReplyChannel.HandleRequest(HttpContext context) at CoreWCF.Channels.RequestDelegateHandler.HandleRequest(HttpContext context) at CoreWCF.Channels.ServiceModelHttpMiddleware.InvokeAsync(HttpContext context) at CoreWCF.Channels.MetadataMiddleware.InvokeAsync(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

l3r0r0 commented 2 years ago

I have had the same situation, after research, I have found that actually you have two ways of doing that: 1- Need to create a custom UserNamePasswordValidator and override ValidateAsync method + configure it in DI:

public class UserTokenValidator : UserNamePasswordValidator
{
    public override ValueTask ValidateAsync(string userName, string password)
    {
        Console.WriteLine($"Username: {userName}, Password: {password}");
        return ValueTask.CompletedTask;
    }
}
 serviceBuilder.ConfigureServiceHostBase<YourServiceName>(serviceHost =>
    {
        serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =
            UserNamePasswordValidationMode.Custom;
        serviceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new UserTokenValidator();
    });

2- You need to create your own ServiceBehavior and configure CustomUserNamePasswordValidator there + Need to create a custom UserNamePasswordValidator. So, to create UserNamePasswordValidator you have to inherit from it and override ValidateAsync method:

public class UserTokenValidator : UserNamePasswordValidator
{
    public override ValueTask ValidateAsync(string userName, string password)
    {
        Console.WriteLine($"Username: {userName}, Password: {password}");
        return ValueTask.CompletedTask;
    }
}

To create you're SecurityBehavior you have to inherit from ServiceBehaviorand implement methods:

public class TestSecurityBehavior : **IServiceBehavior**
{
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        serviceHostBase.Credentials.UserNameAuthentication.UserNamePasswordValidationMode =
            **UserNamePasswordValidationMode.Custom**;
        serviceHostBase.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = **new UserTokenValidator();**
    }
}

at the end need to register SecurityBehavior in DI:

builder.Services.AddSingleton<IServiceBehavior, SecurityBehavior>();

ctechid commented 1 year ago

Look at here

PraveenNunna commented 1 year ago

@l3r0r0 What kind of binding did you use for the custom user name validation? I am using BasicHttpBinding. With this, credentials validation is not happening.

ssmsam12345 commented 1 year ago

Hi Praveen Can you contact me on @.***?

, Sampat

On Thu, Apr 27, 2023, 8:47 PM Praveen Nunna @.***> wrote:

@l3r0r0 https://github.com/l3r0r0 What kind of binding did you use for the custom user name validation? I am using BasicHttpBinding. With this, credentials validation is not happening.

— Reply to this email directly, view it on GitHub https://github.com/CoreWCF/CoreWCF/issues/847#issuecomment-1525884658, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABAGHT7OYLKOPX2H3PEY2M3XDKEZ7ANCNFSM6AAAAAAQTUALUQ . You are receiving this because you modified the open/close state.Message ID: @.***>

AlexiosN13 commented 4 months ago

Hi @PraveenNunna did you manage to trigger the custom validation when using the BasicHttpBinding ?

mconnew commented 4 months ago

Here's an issue with a full solution for using Username/Password validation. Basically you need to do it the asp.net core way, but setting the binding settings for the correct credential type will result in ensuring the auth is challenged correctly (setting up asp.net core doesn't make it challenge, just makes the auth available if the app challenges) and the claims should be available in your app.