Terminologias
Identity Provider (IDP)
O Identity Provider ou Provedor de Identidades implementa os protocolos OpenID Connect e OAuth 2.0.
Diferentes literaturas usam diferentes termos para as mesmas coisas. Você provavelmente também encontrará como:
- serviço de tokens de segurança (Security Token Service ou somente STS);
- Serviço de Identidades (Identity Server);
- Servidor de autorização (Authentication Server);
- IP-STS (Identity Provider Security Token Service);
- e outros.
Mas todos são a mesma coisa: um sistema que gera tokens de segurança para seus clientes.
O Acesso TJTO tem algumas serviços e recursos:
- Proteger seus recursos;
- autenticar usuários usando um armazenamento de conta local ou por meio de um provedor de identidade externo;
- fornecer gerenciamento de sessão e logon único (single sign-on ou SSO);
- gerenciar e autenticar clientes;
- emitir identidade e tokens de acesso aos clientes
- validar tokens
Cliente (Client, Relying Party ou RP)
Um cliente é um software que requisita tokens para o Acesso TJTO, tanto para autenticar um usuário (requisitando um token de identificação ou identity token) ou para acessar um recurso (requisitando um token de acesso ou access token). Um cliente precisa estar registrado no Acesso TJTO antes de requisitar tokens.
Exemplos de clientes:
- Aplicações Web (Web Applications);
- Aplicações para dispositivos móveis (Native mobile applications);
- Aplicações de executáveis (desktop applications);
- etc.
Usuário (User)
Um humano que está usando um cliente registrado para acessar os recursos.
Recursos (Resources)
Recurso é algo que você deseja proteger com o Acesso TJTO. Dados de identidade de seus usuários, funcionalidades dentro do cliente ou APIs. Cada recurso tem um nome exclusivo e os clientes usam esse nome para especificar a quais recursos eles desejam obter acesso.
- Dados de identidade são informações de um usuário (também conhecidos como Claims), por exemplo, nome ou endereço de e-mail.
- APIs (Application Programming Interface) representam a funcionalidade que um cliente deseja invocar - normalmente modeladas como APIs da Web, mas não necessariamente.
Token de identidade (Identity Token)
Um token de identidade representa o resultado de um processo de autenticação. Ele contém, no mínimo, um identificador para o usuário (chamado de sub ou subject claim) e informações sobre como e quando o usuário foi autenticado. Ele pode conter dados de identidade adicionais.
Token de acesso (Access Token)
Um token de acesso permite o acesso a um recurso de API. Os clientes solicitam tokens de acesso e os encaminham para a API. Os tokens de acesso contêm informações sobre o cliente e o usuário (se houver). As APIs usam essas informações para autorizar o acesso aos seus dados.
Especificações
Especificações Suportadas
O Acesso TJTO implementa as seguintes especificações:
Open Id Connect
- OpenID Connect
- OpenID Connect Core 1.0 (spec)
- OpenID Connect Discovery 1.0 (spec)
- OpenID Connect RP-Initiated Logout 1.0 - draft 01 (spec)
- OpenID Connect Session Management 1.0 - draft 30 (spec)
- OpenID Connect Front-Channel Logout 1.0 - draft 04 (spec)
- OpenID Connect Back-Channel Logout 1.0 - draft 06 (spec)
OAuth 2.0
- OAuth 2.0 (RFC 6749)
- OAuth 2.0 Bearer Token Usage (RFC 6750)
- OAuth 2.0 Multiple Response Types (spec)
- OAuth 2.0 Form Post Response Mode (spec)
- OAuth 2.0 Token Revocation (RFC 7009)
- OAuth 2.0 Token Introspection (RFC 7662)
- Proof Key for Code Exchange (RFC 7636)
- JSON Web Tokens for Client Authentication (RFC 7523)
- OAuth 2.0 Device Authorization Grant (RFC 8628)
- OAuth 2.0 Mutual TLS Client Authentication and Certificate-Bound Access Tokens (RFC 8705)
- JWT Secured Authorization Request (draft)
Endpoints
Discovery Endpoint
O discovery endpoint pode ser usado para recuperar os metadados do Acesso TJTO. Ele retorna informações como o nome do emissor (issuer name), key material, escopos suportados (scopes), etc. O discovery endpoint está disponível aqui
Authorize Endpoint
O endpoint de autorização pode ser usado para requisitar tokens ou códigos de autorizações via browser. Este processo tipicamente envolve autenticatação do usuário final e opcionalmente o seu consentimento.
Exemplo:
GET /connect/authorize HTTP/1.1
?client_id=client1
&scope=openid email api1
&response_type=code
&redirect_uri=https://myapp/sigincallback
&state=abc
&nonce=8786548676548676534
(Encoding de url removido, e quebras de linhas adicionados para facilitar a leitura)
Parâmetros obrigatórios:
client_id
scope
response_type
code
- solicita um código de autorização (Padrão)
id_token
- solicita um token de identidade (apenas escopos de identidade são permitidos)
token
- solicita um token de acesso (apenas escopos de recursos são permitidos)
id_token token
- solicita um token de identidade e um token de acesso
code id_token
- solicita um código de autorização e token de identidade
code id_token token
- solicita um código de autorização, token de identidade e token de acesso
redirect_uri
state
nonce
Parâmetros opcionais:
response_mode
form_post
envia a resposta do token como uma postagem do formulário em vez de um redirecionamento codificado por fragmento (opcional)
prompt
none
nenhuma Interface de usuário será mostrada durante a solicitação.
Se isso não for possível (por exemplo, porque o usuário precisa fazer login ou consentir), um erro é retornado
login
a Interface de login será exibida, mesmo se o usuário já estiver conectado e tiver uma sessão válida
code_challenge
code_challenge_method
plain
- indica que o desafio está usando texto simples (não recomendado)
S256
- indica que o desafio é hash com SHA256
max_age
acr_values
idp:name_of_idp
ignora a tela de login/domínio inicial e encaminha o usuário diretamente para o provedor de identidade selecionado
(se permitido pela configuração do cliente)
tenant:name_of_tenant
pode ser usado para passar um nome de locatário para a interface de login
Resposta ao cliente
Quando o usuário for autorizado, o Acesso TJTO chamará a uri definida em redirect_uri
com os seguintes parâmetros:
code
state
Token Endpoint
O token endpoint pode ser usado para requisitar tokens.
Exemplo:
POST /connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZXMSDGDFHRUWEKJSDSKJSSKDJSD12562JKASDSDH38734738KJKFJDFJKDFNEDF859687498564KMDFJKDFJjsdjshdssjdhsjJASHSASHAJSHJHASD238712HFD8SD79FSD8F7DSF8DSUF897SXCJCVHSD789679867GB==
&grant_type=authorization_code
&redirect_uri=https://myapp/sigincallback
&code=hdh922
(Form-Encoding de url removido, e quebras de linhas adicionados para facilitar a leitura)
Deve ser feito um POST com os seguintes parâmetros:
Header:
Content-Type: application/x-www-form-urlencoded
- O conteúdo precisa ser no formato de POST de formulário
Authorization: Basic
- Autorização básica (Basic) com informações do
client id
eclient secret
previamente cadastrados no Acesso TJTO - O
client_secret
deve passar por "url encode" antes de ser codificado na Base64 - Codificar em Base64 uma string com o formato
"client_id:client_secret"
Body:
O POST deve ter os seguintes parâmetros no BODY em formato "application/x-www-form-urlencoded"
Parâmetros obrigatórios:
grant_type (tipo de concessão)
authorization_code
(acesso de usuário)client_credentials
(acesso de api)password
(não recomendado, em desuso)refresh_token
(atualização de token)urn:ietf:params:oauth:grant-type:device_code
(versões futuras)
code
authorization_code
)
redirect_uri
grant_type=authorization_code
Parâmetros opcionais:
code_verifier
username
grant_type=password
)password
grant_type=password
)refresh_token
grant_type=refresh_token
)device_code
urn:ietf:params:oauth:grant-type:device_code
)Resposta ao cliente:
Em caso de sucesso, será retornar um JSON com as informações de autenticação:
{
"access_token": "Token de acesso",
"id_token": "Token de autenticação com informações usuário.",
"token_type": "Bearer",
"expires_in": "Tempo de vida do token"
}
Token Validation Endpoint
O token endpoint pode ser usado para requisitar tokens.
Para verificar se as informações vindas do Acesso TJTO estão corretas e de confiança, é necessário a validação dos tokens através do uso da chave pública disponível
em no endpoint de validação que também está disponível no parâmetro jwks_uri
do discovery endpoint
UserInfo Endpoint
O UserInfo endpoint pode ser usado para recuperar informações de identidade de um usuário (spec).
Exemplo:
GET /connect/userinfo HTTP/1.1 Authorization: Bearer <access_token> HTTP/1.1 200 OK
Content-Type: application/json { "sub": "99999", "name": "Oikram Arieiv", "given_name": "Oikram", "family_name": "Arieiv" }
Device Endpoint
O endpoint de autorização de dispositivo pode ser usado para solicitar o dispositivo e os códigos do usuário. Este ponto de extremidade é usado para iniciar o processo de autorização de fluxo do dispositivo.
Exemplo:
POST /connect/deviceauthorization HTTP/1.1
?client_id=client1
&client_secret=secret
&scope=openid api1
(Form-Encoding de url removido, e quebras de linhas adicionados para facilitar a leitura)
client_id
client_secret
scope
Introspection Endpoint
O introspection endpoint é uma implementação do RFC 7662.
Pode ser usado para validar tokens de referência (ou JWTs se o consumidor não tiver suporte para JWT apropriado ou bibliotecas criptográficas). O endpoint de introspecção requer autenticação, uma vez que o cliente de um endpoint de introspecção é uma API.
Exemplo:
POST /connect/introspect HTTP/1.1
Authorization: Basic xxxyyy
token=45ghiukldjahdnhzdauz
Uma resposta bem-sucedida retornará um código de status de 200 e um token ativo ou inativo:
{
"active": true,
"sub": "123"
}
Tokens desconhecidos ou expirados serão marcados como inativos:
{
"active": false,
}
Uma solicitação inválida retornará um 400, uma solicitação não autorizada 401.
Revocation Endpoint
O revocation endpoint permite revogar tokens de acesso (apenas tokens de referência) e atualizar o token. Ele implementa a especificação de revogação de token (RFC 7009).
Exemplo:
POST /connect/revocation HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
&token=<token>
&token_type_hint=refresh_token
token
token_type_hint
access_token
ou refresh_token
(opcional)
End Session Endpoint
O end session endpoint pode ser usado para acionar o logout único (spec) Para usar endpoint, um aplicativo cliente redirecionará o navegador do usuário para o URL do end session. Todos os aplicativos nos quais o usuário se conectou por meio do navegador durante a sessão do usuário podem participar do signout. A Url do end session endpoint está disponível no discovery endpoint
Exemplo:
GET /connect/endsession HTTP/1.1
?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjdlOGFkZmMzMjU1OTEyNzI0ZDY4NWZmYmIwOThjNDEyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE0OTE3NjUzMjEsImV4cCI6MTQ5MTc2NTYyMSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoianNfb2lkYyIsIm5vbmNlIjoiYTQwNGFjN2NjYWEwNGFmNzkzNmJjYTkyNTJkYTRhODUiLCJpYXQiOjE0OTE3NjUzMjEsInNpZCI6IjI2YTYzNWVmOTQ2ZjRiZGU3ZWUzMzQ2ZjFmMWY1NTZjIiwic3ViIjoiODg0MjExMTMiLCJhdXRoX3RpbWUiOjE0OTE3NjUzMTksImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.STzOWoeVYMtZdRAeRT95cMYEmClixWkmGwVH2Yyiks9BETotbSZiSfgE5kRh72kghN78N3-RgCTUmM2edB3bZx4H5ut3wWsBnZtQ2JLfhTwJAjaLE9Ykt68ovNJySbm8hjZhHzPWKh55jzshivQvTX0GdtlbcDoEA1oNONxHkpDIcr3pRoGi6YveEAFsGOeSQwzT76aId-rAALhFPkyKnVc-uB8IHtGNSyRWLFhwVqAdS3fRNO7iIs5hYRxeFSU7a5ZuUqZ6RRi-bcDhI-djKO5uAwiyhfpbpYcaY_TxXWoCmq8N8uAw9zqFsQUwcXymfOAi2UF3eFZt02hBu-shKA
&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A7017%2Findex.html
id_token_hint
id_token
original recebido da autenticação.
Isso é passado como um parâmetro de string de consulta chamado id_token_hint
.
post_logout_redirect_uri
id_token_hint
válido for passado, o cliente também pode enviar um parâmetro post_logout_redirect_uri
.
Isso pode ser usado para permitir que o usuário redirecione de volta para o cliente após o logout.
O valor deve corresponder a um dos PostLogoutRedirectUris pré-configurados do cliente.
state
post_logout_redirect_uri
válido for passado, o cliente também pode enviar um parâmetro de estado.
Isso será retornado ao cliente como um parâmetro de string de consulta depois que o usuário redirecionar de volta ao cliente.
Isso normalmente é usado por clientes para checar o estado de ida e volta no redirecionamento.
Exemplos
Para todos os casos deve ser solicitado o cadastro prévio do sistema ou API no Acesso TJTO, informando:
- Nome cliente
- Indicar o tipo de grant (ver grant types)
- Descrição de no máximo 100 caracteres
- Url cliente
- Escopos desejados
A implementação do cliente depende da linguagem. Abaixo alguns exemplos:
Para saber mais sobre bibliotecas que podem ser úteis nesse trabalho acesse Certified Relying Party Libraries
C#.NET Core
Para adicionar o Acesso TJTO em uma aplicação .NET Core 3.1 ou superior, no exemplo vamos utilizar uma bibilioteca da Microsoft
Microsoft.AspNetCore.Authentication
public partial class Startup
{
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.Cookies;
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthentication(options =>
{
options.DefaultScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.ClientId = 99999; //Id do cliente previamente cadastrado no Acesso TJTO
options.Authority = "https://idp.tjto.jus.br"; //Endereço do Acesso TJTO
options.ResponseType = "code"; //Grant Type Code
options.RequireHttpsMetadata = true;
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.SignedOutRedirectUri = "";
options.ClientSecret = "xyz"; //Senha do cliente;
options.SaveTokens = true; //para poder ter acesso ao access_token e id_token
options.GetClaimsFromUserInfoEndpoint = true; //Pega as informações do usuário automaticamente
options.UsePkce = true; //Usa PKCE. Depende de configuração prévia no Acesso TJTO
//Adiciona os escopos a serem solicitados
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
//Claims personalizadas não são automaticamente mapeadas pelo .net e precisam ser especificadas
options.ClaimActions.MapUniqueJsonKey("matricula", "matricula");
}
...
}
public void Configure(IApplicationBuilder app)
{
...
app.UseAuthentication();
...
}
}
Após o retorno do login, a aplicação pode pegar os dados do usuário nos Controllers conforme demonstrado abaixo:
var identity = User.Identity as ClaimsIdentity;
var claims = identity.Claims;
var idUsuario = claims.FirstOrDefault(x => x.Type == "sub");
var nome = claims.FirstOrDefault(x => x.Type == "name");
var email = claims.FirstOrDefault(x => x.Type == "email");
Para fazer logout do sistema:
httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
Para fazer logout da conta:
httpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);