Skip to content

Commit

Permalink
Merge pull request #2591 from unoplatform/dev/cdb/iodc-native-options
Browse files Browse the repository at this point in the history
[Oidc-Auth] Allow native OidcClientOptions settings + Redirect URI auto-discovery
  • Loading branch information
carldebilly authored Oct 18, 2024
2 parents 5e2e4a6 + c3e0fc9 commit f06d42b
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 111 deletions.
3 changes: 2 additions & 1 deletion Uno.Extensions.sln
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uno.Extensions.Authenticati
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uno.Extensions.Authentication.MSAL.WinUI", "src\Uno.Extensions.Authentication.MSAL\Uno.Extensions.Authentication.MSAL.WinUI.csproj", "{978A32D5-B542-4E4D-9F2E-AE78752F9633}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BEBE0A7A-DF4F-4250-A50E-6901C936A01B}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Solution Items", "_Solution Items", "{BEBE0A7A-DF4F-4250-A50E-6901C936A01B}"
ProjectSection(SolutionItems) = preProject
src\crosstargeting_override.props = src\crosstargeting_override.props
src\Directory.Build.props = src\Directory.Build.props
src\Directory.Build.targets = src\Directory.Build.targets
src\Directory.Packages.props = src\Directory.Packages.props
Expand Down
61 changes: 49 additions & 12 deletions doc/Learn/Authentication/HowTo-OidcAuthentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ uid: Uno.Extensions.Authentication.HowToOidcAuthentication
---
# How-To: Get Started with Oidc Authentication

`OidcAuthenticationProvider` allows your users to sign in using their identities from a participating identity provider. It can wrap support for any [OpenID Connect](https://openid.net/connect/) backend, such as [IdentityServer](https://duendesoftware.com/products/identityserver) into an implementation of `IAuthenticationProvider`. This tutorial will use the OIDC authorization to validate user credentials.
`OidcAuthenticationProvider` is a specific implementation of `IAuthenticationProvider` that allows your users to sign in using their identities from a participating identity provider. It provides seamless integration with any [OpenID Connect](https://openid.net/connect/) backend, such as [IdentityServer](https://duendesoftware.com/products/identityserver). By acting as an adapter, it integrates OpenID Connect authentication into the Uno.Extensions ecosystem, allowing you to leverage a unified approach across platforms.

Under the hood, `OidcAuthenticationProvider` relies on [IdentityModel.OidcClient](https://identitymodel.readthedocs.io/), a widely-used .NET library that handles the core OpenID Connect and OAuth 2.0 protocols. This library manages the complex operations like token handling and user authentication.

> [!NOTE]
> It may be useful to familiarize yourself with the [OpenID Connect](https://openid.net/connect/) protocol before proceeding.
> You can also explore the [Uno Tutorial for Oidc Authentication](xref:Uno.Tutorials.OpenIDConnect) to learn more about the particularities for different platforms.
## Step-by-step

Expand Down Expand Up @@ -78,17 +84,19 @@ uid: Uno.Extensions.Authentication.HowToOidcAuthentication

- We will use the default section name `Oidc` in this example:

```json
{
"Oidc": {
"Authority": "https://demo.duendesoftware.com/",
"ClientId": "interactive.confidential",
"ClientSecret": "secret",
"Scope": "openid profile email api offline_access",
"RedirectUri": "oidc-auth://callback",
}
}
```
```json
{
"Oidc": {
"Authority": "https://demo.duendesoftware.com/",
"ClientId": "interactive.confidential",
"ClientSecret": "secret",
"Scope": "openid profile email api offline_access",
"RedirectUri": "oidc-auth://callback",
}
}
```

> Common scopes include `openid`, `profile`, `email`, and `offline_access`. The `openid` scope is required for OpenID Connect authentication. The `profile` and `email` scopes are used to request additional user information, and the `offline_access` scope is used to request a refresh token. Your identity provider may provide additional scopes, such as `api`, to request access to specific APIs.
- `Authority`: The URL of the identity provider.

Expand All @@ -97,6 +105,23 @@ uid: Uno.Extensions.Authentication.HowToOidcAuthentication
- `Scope`: The scope of the access token.

- `RedirectUri`: The URL that the identity provider will redirect to after the user has authenticated.
> It is also possible to populate this setting automatically from the WebAuthenticationBroker using the `.AutoRedirectUriFromAuthenticationBroker()` extension method, which will set the redirect URI to the value returned by the `WebAuthenticationBroker.GetCurrentApplicationCallbackUri()` method, which should discover the correct redirect URI for the application/platform. More information can be found in the [Web Authentication Broker documentation](xref:Uno.Features.WAB).
>
> When used, this setting will override the value set in the configuration file for both the redirect URI and the post-logout redirect URI.
> **This setting is ON by default on WebAssembly but opt-in on other platforms.**
- **Advanced settings**: some advanced settings may need to access directly the `OidcClientOptions` from `IdentityModel.OidcClient` used by this extension. This can be done by using the `.ConfigureOidcClientOptions()` extension method.

```csharp
builder.AddOidc()
.ConfigureOidcClientOptions(options =>
{
// Example of advanced settings for the OidcClientOptions
options.DisablePushedAuthorization = false; // Disable the PAR endpoint
options.Policy.RequireIdentityTokenOnRefreshTokenResponse = true; // Require an identity token on refresh token response
options.Policy.Discovery.ValidateIssuerName = false; // Disable issuer name validation
});
```

### 4. Use the provider in your application

Expand Down Expand Up @@ -142,3 +167,15 @@ uid: Uno.Extensions.Authentication.HowToOidcAuthentication
- Finally, we can pass the login credentials to the `LoginAsync()` method and authenticate with the identity provider. The user will be prompted to sign in to their account when they tap the button in the application.

- `OidcAuthenticationProvider` will then store the user's access token in credential storage. The token will be automatically refreshed when it expires.

## Advanced Customizations

- You can use your own implementation of `IBrowser` (an interface from the `IdentityModel.OidcClient` library) to customize the browser behavior. This should be done by creating a class that implements the interface and register it using the `.ConfigureServices()` in the `App.xaml.cs` file.

```csharp
.ConfigureServices((context, services) =>
{
services.AddTransient<IBrowser, CustomBrowser>();
})

```
2 changes: 1 addition & 1 deletion samples/Playground/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PackageVersion Include="SkiaSharp.Views" Version="2.88.7" />
<PackageVersion Include="SkiaSharp.Views.Uno.WinUI" Version="2.88.7" />
<PackageVersion Include="SkiaSharp.Skottie" Version="2.88.7" />
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="Uno.Core" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions.Logging.Singleton" Version="4.1.1" />
<PackageVersion Include="Uno.Extensions.Logging.OSLog" Version="1.7.0" />
Expand Down
136 changes: 66 additions & 70 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,80 +1,76 @@
<Project ToolsVersion="15.0">
<!--
<!--
Due to an issue with duplicate references on output for Windows we need to ensure that when building for MAUI Embedding that we use the same version
of both WinUI and Uno.WinUI across Extensions and the MauiEmbedding Sample Project.
-->
<!-- <PropertyGroup Condition="$(SolutionName) != 'MauiEmbedding'">
<!-- <PropertyGroup Condition="$(SolutionName) != 'MauiEmbedding'">
<UnoVersion Condition="$(UnoVersion) == '' AND !$(MSBuildProjectName.Contains('Maui'))">5.2.175</UnoVersion>
<UnoVersion Condition="$(UnoVersion) == '' AND $(MSBuildProjectName.Contains('Maui'))">5.2.175</UnoVersion>
<WinAppSdkVersion Condition="$(WinAppSdkVersion) == ''">1.5.240311000</WinAppSdkVersion>
</PropertyGroup> -->

<!--<PropertyGroup>
<!--<PropertyGroup>
<UnoToolkitVersion>5.0.15</UnoToolkitVersion>
</PropertyGroup>-->

<ItemGroup>
<PackageVersion Include="CommunityToolkit.Mvvm" Version="7.0.1" />
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.1.1" />
<PackageVersion Include="FluentAssertions" Version="6.7.0" />
<PackageVersion Include="IdentityModel.OidcClient" Version="5.0.0" />
<PackageVersion Include="MSTest.TestAdapter" Version="2.2.9" />
<PackageVersion Include="MSTest.TestFramework" Version="2.2.9" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.61.3" />
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.61.3" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="8.0.3" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.Net.Compilers.Toolset" Version="4.2.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="Microsoft.UI.Xaml" Version="2.7.1" />
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.2.0" />
<PackageVersion Include="Moq" Version="4.17.2" />
<PackageVersion Include="Refit" Version="6.3.2" />
<PackageVersion Include="Refit.HttpClientFactory" Version="6.3.2" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="4.2.0" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageVersion Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageVersion Include="Serilog.Sinks.Xamarin" Version="1.0.0" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Linq.Async" Version="4.0.0" />
<PackageVersion Include="System.Net.Http.WinHttpHandler" Version="6.0.1" />
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="Uno.Core" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions.Collections" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions.Logging.Singleton" Version="4.1.1" />
<PackageVersion Include="Uno.Extensions.Logging.OSLog" Version="1.7.0" />
<PackageVersion Include="Uno.Extensions.Logging.WebAssembly.Console" Version="1.7.0" />
<PackageVersion Include="Uno.Extensions.Markup.Generators" Version="5.3.12" />
<PackageVersion Include="Uno.Extensions.Markup.WinUI" Version="5.3.12" />
<PackageVersion Include="Uno.Roslyn" Version="1.3.0-dev.12" />
<PackageVersion Include="Uno.Toolkit" Version="6.1.8" />
<PackageVersion Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="$(UnoVersion)"/>

<PackageVersion Include="Uno.UI.RuntimeTests.Engine" Version="0.37.0-dev.126" />
<PackageVersion Include="Uno.WinUI" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Markup" Version="5.3.12" />
<PackageVersion Include="Uno.WinUI.MSAL" Version="$(UnoVersion)" />
<PackageVersion Include="coverlet.collector" Version="3.1.2" />
<PackageVersion Include="xunit" Version="2.4.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="FluentValidation" Version="11.4.0" />

<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
</Project>
<ItemGroup>
<PackageVersion Include="CommunityToolkit.Mvvm" Version="7.0.1" />
<PackageVersion Include="DotNet.ReproducibleBuilds" Version="1.1.1" />
<PackageVersion Include="FluentAssertions" Version="6.7.0" />
<PackageVersion Include="IdentityModel.OidcClient" Version="5.0.0" />
<PackageVersion Include="MSTest.TestAdapter" Version="2.2.9" />
<PackageVersion Include="MSTest.TestFramework" Version="2.2.9" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.61.3" />
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.61.3" />
<PackageVersion Include="Microsoft.Maui.Controls" Version="8.0.3" />
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.Net.Compilers.Toolset" Version="4.2.0" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="Microsoft.UI.Xaml" Version="2.7.1" />
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.2.0" />
<PackageVersion Include="Moq" Version="4.17.2" />
<PackageVersion Include="Refit" Version="6.3.2" />
<PackageVersion Include="Refit.HttpClientFactory" Version="6.3.2" />
<PackageVersion Include="Serilog.Extensions.Hosting" Version="4.2.0" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageVersion Include="Serilog.Sinks.Console" Version="4.0.1" />
<PackageVersion Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageVersion Include="Serilog.Sinks.Xamarin" Version="1.0.0" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Linq.Async" Version="4.0.0" />
<PackageVersion Include="System.Net.Http.WinHttpHandler" Version="6.0.1" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="Uno.Core" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions.Collections" Version="4.1.1" />
<PackageVersion Include="Uno.Core.Extensions.Logging.Singleton" Version="4.1.1" />
<PackageVersion Include="Uno.Extensions.Logging.OSLog" Version="1.7.0" />
<PackageVersion Include="Uno.Extensions.Logging.WebAssembly.Console" Version="1.7.0" />
<PackageVersion Include="Uno.Extensions.Markup.Generators" Version="5.3.12" />
<PackageVersion Include="Uno.Extensions.Markup.WinUI" Version="5.3.12" />
<PackageVersion Include="Uno.Roslyn" Version="1.3.0-dev.12" />
<PackageVersion Include="Uno.Toolkit" Version="6.1.8" />
<PackageVersion Include="Uno.UI.Adapter.Microsoft.Extensions.Logging" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.UI.RuntimeTests.Engine" Version="0.37.0-dev.126" />
<PackageVersion Include="Uno.WinUI" Version="$(UnoVersion)" />
<PackageVersion Include="Uno.WinUI.Markup" Version="5.3.12" />
<PackageVersion Include="Uno.WinUI.MSAL" Version="$(UnoVersion)" />
<PackageVersion Include="coverlet.collector" Version="3.1.2" />
<PackageVersion Include="xunit" Version="2.4.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="FluentValidation" Version="11.4.0" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
</Project>
Loading

0 comments on commit f06d42b

Please sign in to comment.