Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Por Damien Bowden
Ver ou transferir código de exemplo
Este artigo abrange as seguintes áreas:
- O que é um cliente interativo confidencial do OpenID Connect
- Criar um cliente OpenID Connect no ASP.NET Core
- Exemplos de cliente OpenID Connect com trechos de código
- Usando clientes de provedores OpenID Connect de terceiros
- Arquitetura de segurança do Backend para Frontend (BFF)
- Recursos avançados, padrões, extensão do cliente OpenID Connect
Para obter uma experiência alternativa usando Biblioteca de Autenticação da Microsoft para .NET, Microsoft Identity Web e ID do Microsoft Entra, consulte o Guia de início rápido: iniciar sessão de utilizadores e chamar a API do Microsoft Graph de uma aplicação Web ASP.NET Core (documentação do Azure).
Para obter um exemplo usando o servidor OIDC de ID Externo do Microsoft Entra, consulte Inicie sessão de utilizadores para um exemplo de aplicação Web ASP.NET Core num locatário externo e Uma aplicação Web ASP.NET Core que autentica utilizadores contra a Microsoft Entra External ID usando o Microsoft Identity Web.
O que é um cliente interativo confidencial do OpenID Connect
OpenID Connect pode ser usado para implementar autenticação em aplicativos ASP.NET Core. A maneira recomendada é usar um cliente confidencial do OpenID Connect usando o fluxo de código. O uso da Chave de Prova para Troca de Código por Clientes Públicos OAuth (PKCE) é recomendado para esta implementação. Tanto o cliente do aplicativo quanto o usuário do aplicativo são autenticados no fluxo confidencial. O cliente do aplicativo usa um segredo do cliente ou uma asserção de cliente para autenticar.
Os clientes públicos OpenID Connect/OAuth não são mais recomendados para aplicativos Web.
O fluxo padrão funciona como mostrado no diagrama a seguir:
OpenID Connect vem em muitas variações e todas as implementações de servidor têm parâmetros e requisitos ligeiramente diferentes. Alguns servidores não suportam o endpoint de informações do utilizador, alguns ainda não suportam PKCE e outros exigem parâmetros especiais no pedido de token. As asserções do cliente podem ser usadas em vez dos segredos do cliente. Também existem novos padrões que adicionam segurança extra ao OpenID Connect Core, por exemplo, FAPI, CIBA ou DPoP para APIs downstream.
Observação
A partir do .NET 9, são usadas por padrão as OAuth 2.0 Solicitações de Autorização Push (PAR) RFC 9126, se o servidor OpenID Connect oferecer suporte a isso. Este é um fluxo de três passos e não um fluxo de dois passos como mostrado acima. (A solicitação de informações do usuário é uma etapa opcional.)
Criar um cliente de fluxo de código Open ID Connect usando Razor Pages
A seção a seguir mostra como implementar um cliente OpenID Connect em um projeto vazio da página ASP.NET Core Razor. A mesma lógica pode ser aplicada a qualquer projeto Web ASP.NET Core, com apenas a integração da interface do usuário sendo diferente.
Adicionar suporte ao OpenID Connect
Adicione os pacotes Microsoft.AspNetCore.Authentication.OpenIdConnect
Nuget ao projeto ASP.NET Core.
Configurar o cliente OpenID Connect
Adicione a autenticação à aplicação web usando builder.Services no arquivo Program.cs
. A configuração depende do servidor OpenID Connect. Cada servidor OpenID Connect requer pequenas diferenças na configuração.
O manipulador OpenID Connect é usado para desafios e terminação de sessão. O cookie é usado para manipular a sessão no aplicativo Web. Os esquemas padrão para a autenticação podem ser especificados conforme necessário.
Para obter mais informações, consulte o ASP.NET Core authentication-handler
guidance.
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");
options.Authority = oidcConfig["Authority"];
options.ClientId = oidcConfig["ClientId"];
options.ClientSecret = oidcConfig["ClientSecret"];
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
options.TokenValidationParameters.RoleClaimType = "roles";
});
Para obter detalhes sobre as diferentes opções do OpenID Connect, consulte Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC).
Para conhecer as diferentes possibilidades de mapeamento de declarações, consulte Mapeamento, personalização e transformação de declarações no ASP.NET Core.
Observação
Os seguintes namespaces são necessários:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
Definir as propriedades de configuração
Adicione as configurações do cliente OpenID Connect às propriedades de configuração do aplicativo. As configurações devem corresponder à configuração do cliente no servidor OpenID Connect. Nenhum segredo deve ser persistido nas configurações do aplicativo onde eles podem ser acidentalmente verificados. Os segredos devem ser armazenados em um local seguro como o Azure Key Vault em ambientes de produção ou em segredos de usuário em um ambiente de desenvolvimento. Para obter mais informações, consulte Armazenamento seguro de segredos de aplicativos em desenvolvimento no ASP.NET Core.
"OpenIDConnectSettings": {
// OpenID Connect URL. (The base URL for the /.well-known/openid-configuration)
"Authority": "<Authority>",
// client ID from the OpenID Connect server
"ClientId": "<Client ID>",
//"ClientSecret": "--stored-in-user-secrets-or-key-vault--"
},
Configuração do caminho de retorno de chamada após término da sessão
O SignedOutCallbackPath (chave de configuração: "SignedOutCallbackPath
") é o caminho da solicitação dentro do caminho base do aplicativo intercetado pelo manipulador OpenID Connect onde o agente do usuário é retornado pela primeira vez após sair do provedor de identidade. O aplicativo de exemplo não define um valor para o caminho porque o valor padrão de "/signout-callback-oidc
" é usado. Depois de intercetar a solicitação, o manipulador OpenID Connect redireciona para o SignedOutRedirectUri ou RedirectUri, se especificado.
Configure o caminho para retorno ao terminar sessão no registo do provedor OIDC da aplicação. No exemplo, a seguir, o placeholder {PORT}
é a porta da aplicação:
https://localhost:{PORT}/signout-callback-oidc
Observação
Ao usar a ID do Microsoft Entra, defina o caminho nas entradas URI de Redirecionamento da configuração da plataforma Web no portal do Entra ou do Azure. Uma porta não é necessária para endereços localhost
ao usar o Entra. A maioria dos outros provedores OIDC requer a porta correta. Se não adicionares o URI do caminho de callback desconectado ao registo da aplicação no Entra, este recusa-se a redirecionar o utilizador de volta para a aplicação, pedindo apenas que encerre a janela do navegador.
Atualize o método de pipeline ASP.NET Core na classe de programa.
O método UseRouting
deve ser implementado antes do método UseAuthorization
.
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
// Authorization is applied for middleware after the UseAuthorization method
app.UseAuthorization();
app.MapRazorPages();
Autorização forçada
Adicione o atributo [Authorize]
às páginas de Razor protegidas:
[Authorize]
Uma abordagem melhor é forçar a autorização para todo o aplicativo e desativar páginas não seguras:
var requireAuthPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
builder.Services.AddAuthorizationBuilder()
.SetFallbackPolicy(requireAuthPolicy);
Desative a autorização em pontos de extremidade públicos aplicando o [AllowAnonymous]
atributo aos pontos de extremidade públicos. Para obter exemplos, consulte as seções Adicionar uma nova página Logout.cshtml
e SignedOut.cshtml
Razor páginas ao projeto e Implementar Login
páginas.
Adicionar novas páginas Logout.cshtml
e SignedOut.cshtml
Razor ao projeto
Um logout é necessário para sair da sessão cookie e da sessão OpenID Connect. Toda a aplicação precisa redirecionar para o servidor OpenID Connect para efetuar o registo de saída. Após um registo de saída bem-sucedido, a aplicação abre a rota RedirectUri
.
Implemente uma página de saída padrão e altere o código da página Razor Logout
para o seguinte:
[Authorize]
public class LogoutModel : PageModel
{
public IActionResult OnGetAsync()
{
return SignOut(new AuthenticationProperties
{
RedirectUri = "/SignedOut"
},
// Clear auth cookie
CookieAuthenticationDefaults.AuthenticationScheme,
// Redirect to OIDC provider signout endpoint
OpenIdConnectDefaults.AuthenticationScheme);
}
}
O SignedOut.cshtml
requer o atributo [AllowAnonymous]
:
[AllowAnonymous]
public class SignedOutModel : PageModel
{
public void OnGet()
{
}
}
Implementar página Login
Uma página Login
Razor também pode ser implementada para chamar diretamente o ChallengeAsync
com o necessário AuthProperties
. Isso não é necessário se o aplicativo Web exigir autenticação e o desafio padrão for usado.
A página Login.cshtml
requer o atributo [AllowAnonymous]
:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPageOidc.Pages;
[AllowAnonymous]
public class LoginModel : PageModel
{
[BindProperty(SupportsGet = true)]
public string? ReturnUrl { get; set; }
public async Task OnGetAsync()
{
var properties = GetAuthProperties(ReturnUrl);
await HttpContext.ChallengeAsync(properties);
}
private static AuthenticationProperties GetAuthProperties(string? returnUrl)
{
const string pathBase = "/";
// Prevent open redirects.
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = pathBase;
}
else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative))
{
returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery;
}
else if (returnUrl[0] != '/')
{
returnUrl = $"{pathBase}{returnUrl}";
}
return new AuthenticationProperties { RedirectUri = returnUrl };
}
}
Adicionar um botão de login e logout para o usuário
@if (Context.User.Identity!.IsAuthenticated)
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Logout">Logout</a>
</li>
<span class="nav-link text-dark">Hi @Context.User.Identity.Name</span>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Login</a>
</li>
}
Exemplos com trechos de código
Exemplo usando o endpoint de informação do utilizador
As opções do OpenID Connect podem ser usadas para mapear declarações, implementar manipuladores ou até mesmo salvar os tokens na sessão para uso posterior.
A opção Scope
pode ser usada para solicitar declarações diferentes ou um token de atualização que é enviado como informação para o servidor OpenID Connect. Solicitar o offline_access
é pedir ao servidor para retornar um token de referência que pode ser usado para atualizar a sessão sem autenticar o usuário do aplicativo novamente.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");
options.Authority = oidcConfig["IdentityProviderUrl"];
options.ClientSecret = oidcConfig["ClientSecret"];
options.ClientId = oidcConfig["Audience"];
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("offline_access");
options.ClaimActions.Remove("amr");
options.ClaimActions.MapUniqueJsonKey("website", "website");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
// .NET 9 feature
options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Require;
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
});
Implementando provedores de identidade da Microsoft
A Microsoft tem vários provedores de identidade e implementações do OpenID Connect. A Microsoft tem diferentes servidores OpenID Connect:
- Microsoft Entra ID
- Microsoft Entra ID Externo
- Azure AD B2C
Se estiver autenticando usando um dos provedores de identidade da Microsoft no ASP.NET Core, é recomendável usar os pacotes Microsoft.Identity.Web
Nuget.
Os Microsoft.Identity.Web
pacotes Nuget são clientes específicos da Microsoft construídos sobre o cliente ASP.NET Core OpenID Connect com algumas alterações feitas no cliente padrão.
Usando clientes de provedores OpenID Connect de terceiros
Muitas implementações de servidor OpenID Connect criam pacotes Nuget que são otimizados para a mesma implementação OpenID Connect. Esses pacotes implementam as especificidades do cliente OpenID Connect com os extras exigidos pelo servidor OpenID Connect específico.
Microsoft.Identity.Web
é um exemplo disso.
Se implementar vários clientes OpenID Connect de diferentes servidores OpenID Connect em um único aplicativo, normalmente é melhor reverter para a implementação padrão do ASP.NET Core, pois os diferentes clientes substituem algumas opções que afetam os outros clientes.
OpenIddict Web providers é uma implementação de cliente que suporta muitas implementações de servidor diferentes.
IdentityModel
é uma biblioteca auxiliar padrão do .NET para identidade baseada em declarações, OAuth 2.0 e OpenID Connect. Isso também pode ser usado para ajudar com a implementação do cliente.
Arquitetura de segurança do Backend para Frontend (BFF)
Não é mais recomendado implementar clientes públicos OpenID Connect para qualquer aplicativo Web.
Para obter mais informações, consulte o rascunho do OAuth 2.0 para Browser-Based Applications.
Se estiver a implementar aplicações web que não tenham um back-end independente, recomendamos o uso da arquitetura de segurança do padrão Backend for Frontend (BFF). Esse padrão pode ser implementado de maneiras diferentes, mas a autenticação é sempre implementada no back-end e nenhum dado confidencial é enviado ao cliente da Web para posterior autorização ou fluxos de autenticação.
Recursos avançados, padrões, estendendo o cliente OIDC
Registo
Depurar os clientes OpenID Connect pode ser difícil. Os dados de informações de identificação pessoal (PII) não são registrados por padrão. Se a depuração estiver no modo de desenvolvimento, o IdentityModelEventSource.ShowPII
pode ser usado para registrar dados pessoais confidenciais. Não implante um aplicativo com IdentityModelEventSource.ShowPII
em servidores produtivos.
//using ...
using Microsoft.IdentityModel.Logging;
var builder = WebApplication.CreateBuilder(args);
//... code
var app = builder.Build();
IdentityModelEventSource.ShowPII = true;
//... code
app.Run();
Para obter mais informações, consulte Logging.
Observação
Talvez você queira baixar o nível de log configurado para ver todos os logs necessários.
Personalização de parâmetros OIDC e OAuth
A opção de manipuladores de autenticação OAuth e OIDC (AdditionalAuthorizationParameters) permite a personalização de parâmetros de mensagem de autorização que geralmente são incluídos como parte da cadeia de caracteres de consulta de redirecionamento.
Mapear declarações do OpenID Connect
Para obter mais informações, consulte Mapeamento, personalização e transformação de declarações no ASP.NET Core.
Blazor OpenID Connect
Para obter mais informações, consulte Proteger um ASP.NET Core Blazor Web App com OpenID Connect (OIDC).