Browse Source

Update authentication.

release/3.x.x
Christian Kratky 5 years ago
parent
commit
591ccfec29
5 changed files with 42 additions and 15 deletions
  1. +1
    -1
      Source/MQTTnet.Server/MQTTnet.Server.csproj
  2. +11
    -4
      Source/MQTTnet.Server/Web/BasicAuthenticationHandler.cs
  3. +15
    -5
      Source/MQTTnet.Server/Web/Startup.cs
  4. +13
    -3
      Source/MQTTnet.Server/Web/authorization_handler.py
  5. +2
    -2
      Source/MQTTnet.Server/appsettings.json

+ 1
- 1
Source/MQTTnet.Server/MQTTnet.Server.csproj View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">


<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>


+ 11
- 4
Source/MQTTnet.Server/Web/BasicAuthenticationHandler.cs View File

@@ -18,7 +18,12 @@ namespace MQTTnet.Server.Web
{ {
private readonly ILogger<AuthenticationHandler> _logger; private readonly ILogger<AuthenticationHandler> _logger;


public AuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory loggerFactory, UrlEncoder encoder, ISystemClock clock, ILogger<AuthenticationHandler> logger)
public AuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory loggerFactory,
UrlEncoder encoder,
ISystemClock clock,
ILogger<AuthenticationHandler> logger)
: base(options, loggerFactory, encoder, clock) : base(options, loggerFactory, encoder, clock)
{ {
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -26,11 +31,9 @@ namespace MQTTnet.Server.Web


protected override async Task<AuthenticateResult> HandleAuthenticateAsync() protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{ {
await Task.CompletedTask;
if (!Request.Headers.ContainsKey(HeaderNames.Authorization)) if (!Request.Headers.ContainsKey(HeaderNames.Authorization))
{ {
return AuthenticateResult.Fail("Missing Authorization Header");
return AuthenticateResult.NoResult();
} }


try try
@@ -83,6 +86,10 @@ namespace MQTTnet.Server.Web


return AuthenticateResult.Fail(exception); return AuthenticateResult.Fail(exception);
} }
finally
{
await Task.CompletedTask;
}
} }


private bool ValidateUser(PythonDictionary context) private bool ValidateUser(PythonDictionary context)


+ 15
- 5
Source/MQTTnet.Server/Web/Startup.cs View File

@@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -15,6 +17,7 @@ using MQTTnet.Server.Logging;
using MQTTnet.Server.Mqtt; using MQTTnet.Server.Mqtt;
using MQTTnet.Server.Scripting; using MQTTnet.Server.Scripting;
using MQTTnet.Server.Scripting.DataSharing; using MQTTnet.Server.Scripting.DataSharing;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;


namespace MQTTnet.Server.Web namespace MQTTnet.Server.Web
@@ -115,17 +118,22 @@ namespace MQTTnet.Server.Web
services.AddSwaggerGen(c => services.AddSwaggerGen(c =>
{ {
c.DescribeAllEnumsAsStrings(); c.DescribeAllEnumsAsStrings();
c.AddSecurityDefinition("Basic", new OpenApiSecurityScheme
var securityScheme = new OpenApiSecurityScheme
{ {
Scheme = "Basic", Scheme = "Basic",
Name = HeaderNames.Authorization, Name = HeaderNames.Authorization,
Type = SecuritySchemeType.Http, Type = SecuritySchemeType.Http,
In = ParameterLocation.Header In = ParameterLocation.Header
});
};

c.AddSecurityDefinition("Swagger", securityScheme);

c.AddSecurityRequirement(new OpenApiSecurityRequirement c.AddSecurityRequirement(new OpenApiSecurityRequirement
{ {
[new OpenApiSecurityScheme { Name = "Basic" }] = new List<string>()
[securityScheme] = new List<string>()
}); });

c.SwaggerDoc("v1", new OpenApiInfo c.SwaggerDoc("v1", new OpenApiInfo
{ {
Title = "MQTTnet.Server API", Title = "MQTTnet.Server API",
@@ -145,7 +153,9 @@ namespace MQTTnet.Server.Web
}); });
}); });


services.AddAuthentication("Basic").AddScheme<AuthenticationSchemeOptions, AuthenticationHandler>("Basic", null);
services.AddAuthentication("Basic")
.AddScheme<AuthenticationSchemeOptions, AuthenticationHandler>("Basic", null)
.AddCookie();
} }


private void ReadMqttSettings(IServiceCollection services) private void ReadMqttSettings(IServiceCollection services)
@@ -200,7 +210,7 @@ namespace MQTTnet.Server.Web
} }
else else
{ {
context.Response.StatusCode = 400;
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
} }
} }
else else


+ 13
- 3
Source/MQTTnet.Server/Web/authorization_handler.py View File

@@ -2,9 +2,19 @@
""" """
This function is invoked whenever a user tries to access protected HTTP resources. This function is invoked whenever a user tries to access protected HTTP resources.
This function must exist and return a proper value. Otherwise the request is denied. This function must exist and return a proper value. Otherwise the request is denied.
All authentication data must be sent via using the "Authorization" header. This header
will be parsed and all values will be exposed to the context.
""" """
header_value = context["header_value"] # The untouched header value.


username = context["username"]
password = context["password"]
scheme = context["scheme"]
parameter = context["parameter"]


context["is_authenticated"] = True # Change this to _False_ in case of invalid credentials.
username = context["username"] # Only set if proper "Basic" authorization is used.
password = context["password"] # Only set if proper "Basic" authorization is used.
context["is_authenticated"] = True # Change this to _False_ in case of invalid credentials.

# Example for an API key with proper format.
if header_value == "APIKey 123456":
context["is_authenticated"] = True

+ 2
- 2
Source/MQTTnet.Server/appsettings.json View File

@@ -38,10 +38,10 @@
}, },
"CommunicationTimeout": 15, // In seconds. "CommunicationTimeout": 15, // In seconds.
"ConnectionBacklog": 10, // Set 0 to disable "ConnectionBacklog": 10, // Set 0 to disable
"EnablePersistentSessions": false,
"EnablePersistentSessions": true,
"MaxPendingMessagesPerClient": 250, "MaxPendingMessagesPerClient": 250,
"RetainedApplicationMessages": { "RetainedApplicationMessages": {
"Persist": false,
"Persist": true,
"Path": "RetainedApplicationMessages.json", "Path": "RetainedApplicationMessages.json",
"WriteInterval": 10 // In seconds. "WriteInterval": 10 // In seconds.
}, },


Loading…
Cancel
Save