' Sign in with the EU Digital Identity Wallet - ASP.NET Core 8 in Visual Basic (Program.vb) ' CodeB acts as the verifier: it asks the user's wallet for a presentation, ' verifies it, and hands your app a signed OpenID Connect id_token. ' ' dotnet new console -lang VB -n WalletSignIn -f net8.0 && cd WalletSignIn ' (in WalletSignIn.vbproj set Sdk="Microsoft.NET.Sdk.Web") ' dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect --version 8.0.* ' (replace Program.vb with this file) ' CODEB_CLIENT_ID=... CODEB_CLIENT_SECRET=... dotnet run ' ' Register https:///callback as redirect URI for your client first. Imports System.Security.Claims Imports Microsoft.AspNetCore.Authentication Imports Microsoft.AspNetCore.Authentication.Cookies Imports Microsoft.AspNetCore.Authentication.OpenIdConnect Imports Microsoft.AspNetCore.Builder Imports Microsoft.AspNetCore.Http Imports Microsoft.Extensions.DependencyInjection Module Program ReadOnly WalletAcrs As String() = {"urn:codeb:acr:eudi-wallet", "urn:codeb:acr:eudi-wallet-linked"} Function Env(key As String, fallback As String) As String Dim v = Environment.GetEnvironmentVariable(key) Return If(String.IsNullOrEmpty(v), fallback, v) End Function Sub Main(args As String()) Dim builder = WebApplication.CreateBuilder(args) builder.Services.AddAuthentication( Sub(o) o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme End Sub). AddCookie(). AddOpenIdConnect( Sub(o) o.Authority = Env("CODEB_ISSUER", "https://phone.aloaha.com") o.ClientId = Env("CODEB_CLIENT_ID", "") o.ClientSecret = Env("CODEB_CLIENT_SECRET", "") o.CallbackPath = "/callback" o.ResponseType = "code" ' authorization code flow, PKCE is on by default o.Scope.Clear() o.Scope.Add("openid") : o.Scope.Add("profile") : o.Scope.Add("email") o.MapInboundClaims = False ' keep the original claim names (sub, acr) o.ClaimActions.Remove("acr") ' the handler drops acr from the sign-in cookie by default; keep it o.Events = New OpenIdConnectEvents With { .OnRedirectToIdentityProvider = Function(ctx) ' straight to the wallet sign-in ctx.ProtocolMessage.AcrValues = WalletAcrs(0) Return Task.CompletedTask End Function, .OnTokenValidated = Function(ctx) ' the id_token is already validated (signature, issuer, audience, nonce, expiry); now require the wallet acr Dim acr = ctx.Principal?.FindFirst("acr")?.Value If acr Is Nothing OrElse Array.IndexOf(WalletAcrs, acr) < 0 Then ctx.HandleResponse() ctx.Response.StatusCode = 403 Return ctx.Response.WriteAsync("This page needs a sign-in with the EU Digital Identity Wallet (acr=" & acr & ").") End If Return Task.CompletedTask End Function } End Sub) builder.Services.AddAuthorization() Dim app = builder.Build() app.UseAuthentication() app.UseAuthorization() app.MapGet("/", Function(user As ClaimsPrincipal) As IResult If user.Identity IsNot Nothing AndAlso user.Identity.IsAuthenticated Then Return Results.Text("Signed in as " & user.FindFirst("sub")?.Value & " (acr=" & user.FindFirst("acr")?.Value & ")") End If Return Results.Content("Sign in with your EU Digital Identity Wallet", "text/html") End Function) app.MapGet("/login", Function() Results.Challenge(New AuthenticationProperties With {.RedirectUri = "/"}, New List(Of String) From {OpenIdConnectDefaults.AuthenticationScheme})) app.Run() End Sub End Module