Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .build/release.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<Company>DarkLoop</Company>
<Copyright>DarkLoop - All rights reserved</Copyright>
<Product>DarkLoop's Azure Functions Authorization</Product>
<IsPreview>false</IsPreview>
<IsPreview>true</IsPreview>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<Version>4.0.1</Version>
<Version>4.1.0</Version>
<FileVersion>$(Version).0</FileVersion>
<RepositoryUrl>https://github.com/dark-loop/functions-authorize</RepositoryUrl>
<License>https://github.com/dark-loop/functions-authorize/blob/master/LICENSE</License>
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,5 @@ ASALocalRun/

# MFractors (Xamarin productivity tool) working folder
.mfractor/
/sample/SampleInProcFunctions.V4/Properties/ServiceDependencies/dl-inproc-func - Zip Deploy
/sample/SampleIsolatedFunctions.V4/Properties/serviceDependencies.dl-isloated-func - Zip Deploy.json
84 changes: 84 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Change log
Change log stars with version 3.1.3

## 4.1.0
- ### [Breaking] Removing support for `Bearer` scheme and adding `FunctionsBearer`
Recent security updates in the Azure Functions runtime are clashing with the use of the default, well known `Bearer` scheme.<br/>
One of the effects of this change is the portal not able to interact with the functions app to retrieve runtime information and in some cases not able to retrieve functions information.
In the past this was not an issue and application was able to replace the default `Bearer` configuration to enable the functionality provided by this package.<br/>
Starting from this version, using the default `AddJwtBearer` with no custom name, will produce an error. You will have 2 options: you can switch your app to use `AddJwtFunctionsBearer` method without providing any name which will map your configuration to the `FunctionsBearer` scheme, or you can use `AddJwtBearer("<your-custom-scheme>", ...)` to specify something different.

## 4.0.1
Deprecating `DarkLoop.Azure.Functions.Authorize` package in favor of `DarkLoop.Azure.Functions.Authorization.InProcess` package.<br/>
The functionality remains the same, it's just a way to keep package naming in sync.

## 4.0.0
Starting from 4.0.0, support for Azure Functions V4 Isolated mode with ASPNET Core integration is added.
The package is now split into two separate packages, one for each mode.

The package for Azure Functions V3+ In-Proc mode is now called `DarkLoop.Azure.Functions.Authorization.InProcess` and the package for Azure Functions V4 Isolated mode with ASPNET Core integration is called `DarkLoop.Azure.Functions.Authorize.Isolated`.

- ### .NET 6 support
Starting with version 4.0.0, the package is now targeting .NET 6.0. This means that the package is no longer compatible with .NET 5 or lower. If you are using .NET 5 or lower, you should use version 3.1.3 of the package.

- ### DarkLoop.Azure.Functions.Authorize v4.0.0
This package is published but is now deprecated in favor of `DarkLoop.Azure.Functions.Authorization.InProcess`. All it's functionality remains the same. It's just a way to keep package naming in sync.

- ### Introducing IFunctionsAuthorizationProvider interface
The `IFunctionsAuthorizationProvider` interface is introduced to allow for custom authorization filter provisioning to the framework.
By default the framework relies on decorating the function or type with `[FunctionAuthorize]`. You could skip this decoration and provide the middleware with an authorization filter sourced from your own mechanism, for example a database.
At this moment this can be done only with Isolated mode even when the interface is defined in the shared package.<br/>
Support for In-Process will be added in a future version, once source generators are introduced, as the in-process framework relies on Invocation Filters to enable authorization.
Replacing the service in the application services would break the authorization for in-process mode at this point.

## 3.1.3
3.1.3 and lower versions only support Azure Functions V3 In-Proc mode. Starting from 4.0.0, support for Azure Functions V4 Isolated mode with ASPNET Core integration is added.
- ### Support for disabling `FunctionAuthorize` effect at the application level.
Adding support for disabling the effect of `[FunctionAuthorize]` attribute at the application level.
This is useful when wanting to disable authorization for a specific environment, such as local development.

When configuring services, you can now configure `FunctionsAuthorizationOptions`.
```csharp
builder.Services.Configure<FunctionsAuthorizationOptions>(options =>
options.DisableAuthorization = Configuration.GetValue<bool>("AuthOptions:DisableAuthorization"));
```

Optionally you can bind it to configuration to rely on providers like User Secrets or Azure App Configuration to disable and re-enable without having to restart your application:
```csharp
builder.Services.Configure<FunctionsAuthorizationOptions>(
Configuration.GetSection("FunctionsAuthorization"));
```

For function apps targeting .NET 7 or greater, you can also use `AuthorizationBuilder` to set this value:
```csharp
builder.Services
.AddAuthorizationBuilder()
.DisableAuthorization(Configuration.GetValue<bool>("AuthOptions:DisableAuthorization"));
```

It's always recommended to encapsulate this logic within checks for environments to ensure that if the configuration setting is unintentionally moved to a non-desired environment, it would not affect security of our HTTP triggered functions. This change adds a helper method to identify if you are running the function app in the local environment:
```csharp
if (builder.IsLocalAuthorizationContext())
{
builder.Services.Configure<FunctionsAuthorizationOptions>(
options => options.AuthorizationDisabled = true);
}
```

If you want to output warnings emitted by the library remember to set the log level to `Warning` or lower for `Darkloop` category in your `host.json` file:

```json
{
"logging": {
"logLevel": {
"DarkLoop": "Warning"
}
}
}
```

Thanks to [BenjaminWang1031](https://github.com/BenjaminWang1031) for the suggestion to add this functionality.

- #### Remove Functions bult-in JwtBearer configuration by default
Azure Functions recently [added configuration](https://github.com/Azure/azure-functions-host/pull/9678) for issuer and audience validation for the default authentication flows, not the one supported by this package through `FunctionAuthorizeAttribute`, which interferes with token validation when using our own Bearer scheme token configuration.
In prior versions, this package has functionality to clear Functions built-in configuration, but it was not enabled by default when using `AddJwtBearer(Action<JwtBearerOptions> configure, bool removeBuiltInConfig = false)`. Since the use of this package is commonly used for custom JWT token, the default value of `removeBuiltInConfig` is now `true`.
1 change: 1 addition & 0 deletions Functions-Authorize.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".root", ".root", "{3A9A7517
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
ChangeLog.md = ChangeLog.md
LICENSE = LICENSE
NuGet.Config = NuGet.Config
README.md = README.md
Expand Down
79 changes: 2 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,80 +17,5 @@ This projects is open source and may be redistributed under the terms of the [Ap
### Builds
![master build status](https://dev.azure.com/darkloop/DarkLoop%20Core%20Library/_apis/build/status/Open%20Source/Functions%20Authorize%20-%20Pack?branchName=master)

## Change log
Adding change log starting with version 3.1.3

### 4.0.1
Deprecating `DarkLoop.Azure.Functions.Authorize` package in favor of `DarkLoop.Azure.Functions.Authorization.InProcess` package.<br/>
The functionality remains the same, it's just a way to keep package naming in sync.

### 4.0.0
Starting from 4.0.0, support for Azure Functions V4 Isolated mode with ASPNET Core integration is added.
The package is now split into two separate packages, one for each mode.

The package for Azure Functions V3+ In-Proc mode is now called `DarkLoop.Azure.Functions.Authorization.InProcess` and the package for Azure Functions V4 Isolated mode with ASPNET Core integration is called `DarkLoop.Azure.Functions.Authorize.Isolated`.

- #### .NET 6 support
Starting with version 4.0.0, the package is now targeting .NET 6.0. This means that the package is no longer compatible with .NET 5 or lower. If you are using .NET 5 or lower, you should use version 3.1.3 of the package.

- #### DarkLoop.Azure.Functions.Authorize v4.0.0
This package is published but is now deprecated in favor of `DarkLoop.Azure.Functions.Authorization.InProcess`. All it's functionality remains the same. It's just a way to keep package naming in sync.

- #### Introducing IFunctionsAuthorizationProvider interface
The `IFunctionsAuthorizationProvider` interface is introduced to allow for custom authorization filter provisioning to the framework.
By default the framework relies on decorating the function or type with `[FunctionAuthorize]`. You could skip this decoration and provide the middleware with an authorization filter sourced from your own mechanism, for example a database.
At this moment this can be done only with Isolated mode even when the interface is defined in the shared package.<br/>
Support for In-Process will be added in a future version, once source generators are introduced, as the in-process framework relies on Invocation Filters to enable authorization.
Replacing the service in the application services would break the authorization for in-process mode at this point.

### 3.1.3
3.1.3 and lower versions only support Azure Functions V3 In-Proc mode. Starting from 4.0.0, support for Azure Functions V4 Isolated mode with ASPNET Core integration is added.
- #### Support for disabling `FunctionAuthorize` effect at the application level.
Adding support for disabling the effect of `[FunctionAuthorize]` attribute at the application level.
This is useful when wanting to disable authorization for a specific environment, such as local development.

When configuring services, you can now configure `FunctionsAuthorizationOptions`.
```csharp
builder.Services.Configure<FunctionsAuthorizationOptions>(options =>
options.DisableAuthorization = Configuration.GetValue<bool>("AuthOptions:DisableAuthorization"));
```

Optionally you can bind it to configuration to rely on providers like User Secrets or Azure App Configuration to disable and re-enable without having to restart your application:
```csharp
builder.Services.Configure<FunctionsAuthorizationOptions>(
Configuration.GetSection("FunctionsAuthorization"));
```

For function apps targeting .NET 7 or greater, you can also use `AuthorizationBuilder` to set this value:
```csharp
builder.Services
.AddAuthorizationBuilder()
.DisableAuthorization(Configuration.GetValue<bool>("AuthOptions:DisableAuthorization"));
```

It's always recommended to encapsulate this logic within checks for environments to ensure that if the configuration setting is unintentionally moved to a non-desired environment, it would not affect security of our HTTP triggered functions. This change adds a helper method to identify if you are running the function app in the local environment:
```csharp
if (builder.IsLocalAuthorizationContext())
{
builder.Services.Configure<FunctionsAuthorizationOptions>(
options => options.AuthorizationDisabled = true);
}
```

If you want to output warnings emitted by the library remember to set the log level to `Warning` or lower for `Darkloop` category in your `host.json` file:

```json
{
"logging": {
"logLevel": {
"DarkLoop": "Warning"
}
}
}
```

Thanks to [BenjaminWang1031](https://github.com/BenjaminWang1031) for the suggestion to add this functionality.

- #### Remove Functions bult-in JwtBearer configuration by default
Azure Functions recently [added configuration](https://github.com/Azure/azure-functions-host/pull/9678) for issuer and audience validation for the default authentication flows, not the one supported by this package through `FunctionAuthorizeAttribute`, which interferes with token validation when using our own Bearer scheme token configuration.
In prior versions, this package has functionality to clear Functions built-in configuration, but it was not enabled by default when using `AddJwtBearer(Action<JwtBearerOptions> configure, bool removeBuiltInConfig = false)`. Since the use of this package is commonly used for custom JWT token, the default value of `removeBuiltInConfig` is now `true`.
## Change Log
You can access the change log [here](https://github.com/dark-loop/functions-authorize/blob/master/ChangeLog.md).
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
</PropertyGroup>

<ItemGroup>
<None Remove="Properties\ServiceDependencies\dl-inproc-func - Zip Deploy\profile.arm.json" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.2" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="[4.3.0,)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\in-proc\DarkLoop.Azure.Functions.Authorization.InProcess.csproj" />
<ProjectReference Include="..\..\test\Common.Tests\Common.Tests.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand All @@ -29,4 +35,5 @@
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>

</Project>
29 changes: 15 additions & 14 deletions sample/SampleInProcFunctions.V4/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ public override void Configure(IFunctionsHostBuilder builder)
builder.Services
.AddFunctionsAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtFunctionsBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtFunctionsBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtFunctionsBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
.AddJwtFunctionsBearer(options =>
{
// this line is here to bypass the token validation
// and test the functionality of this library.
Expand All @@ -37,16 +38,16 @@ public override void Configure(IFunctionsHostBuilder builder)

// this is what you should look for in a real-world scenario
// comment the lines if you cloned this repository and want to test the library
options.Authority = "https://login.microsoftonline.com/<your-tenant>";
options.Audience = "<your-audience>";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
};
}, true);
//options.Authority = "https://login.microsoftonline.com/<your-tenant>";
//options.Audience = "<your-audience>";
//options.TokenValidationParameters = new TokenValidationParameters
//{
// ValidateIssuer = true,
// ValidateAudience = true,
// ValidateLifetime = true,
// ValidateIssuerSigningKey = true,
//};
});

builder.Services.AddFunctionsAuthorization(options =>
{
Expand All @@ -65,7 +66,7 @@ public override void Configure(IFunctionsHostBuilder builder)

public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
{
builder.ConfigurationBuilder.AddUserSecrets<Startup>(false, reloadOnChange: true);
builder.ConfigurationBuilder.AddUserSecrets<Startup>(true, reloadOnChange: true);

Configuration = builder.ConfigurationBuilder.Build();

Expand Down
3 changes: 2 additions & 1 deletion sample/SampleInProcFunctions.V4/host.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
}
},
"logLevel": {
"Darkloop": "Information"
"Darkloop": "Information",
"Microsoft": "Information"
}
}
}
1 change: 1 addition & 0 deletions sample/SampleIsolatedFunctions.V4/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
*.arm.json
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
Expand Down
5 changes: 3 additions & 2 deletions sample/SampleIsolatedFunctions.V4/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.IdentityModel.Tokens.Jwt;
using Common.Tests;
using DarkLoop.Azure.Functions.Authorization;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -29,8 +30,8 @@
.ConfigureServices(services =>
{
services
.AddFunctionsAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
.AddFunctionsAuthentication(JwtFunctionsBearerDefaults.AuthenticationScheme)
.AddJwtFunctionsBearer(options =>
{
// this line is here to bypass the token validation
// and test the functionality of this library.
Expand Down
Loading