Proteger recursos da organização
Além de Proteger sua API, que considera a API como o recurso, a organização também pode ser um recurso, e proteger seu recurso de organização da mesma forma. Neste artigo, vamos nos concentrar em como mudar para proteger seu recurso de organização de maneira semelhante.
Passo 1: Obter IDs de organização do fluxo OIDC
Logto estende o protocolo padrão OpenID Connect para permitir que seu aplicativo obtenha as informações da organização do usuário. Existem duas maneiras de fazer isso:
- Se você estiver usando um Logto SDK com suporte a Organizações, pode adicionar o escopo
urn:logto:scope:organizations
ao parâmetroscopes
do objeto de configuração. Normalmente, o SDK terá um enum para esse escopo, por exemplo,UserScope.Organizations
nos Logto JS SDKs.
- JavaScript
- React
- Python
- PHP
- Swift
- Outros
import { LogtoClient, UserScope } from '@logto/browser'; // ou @logto/node, @logto/client
const logto = new LogtoClient({
// ...
scopes: [UserScope.Organizations],
});
import { LogtoProvider, UserScope } from '@logto/react';
const App = () => (
<LogtoProvider
config={{
// ...
scopes: [UserScope.Organizations],
}}
>
{/* ... */}
</LogtoProvider>
);
from logto import UserInfoScope
client = LogtoClient(
LogtoConfig(
# ...
scopes=[UserInfoScope.organizations],
)
)
use Logto\Sdk\Constants\UserScope;
$client = new LogtoClient(
new LogtoConfig(
// ...
scopes: [UserScope::organizations],
)
);
import Logto
import LogtoClient
let config = try? LogtoConfig(
// ...
scopes: [
UserScope.organizations.rawValue,
],
// ...
)
let client = LogtoClient(useConfig: config)
const config = {
// ...
scope: 'openid offline_access urn:logto:scope:organizations',
};
- Para outros casos, você precisa adicionar o escopo
urn:logto:scope:organizations
ao parâmetroscope
da configuração do SDK (ou solicitação de autenticação).
Uma vez que o usuário conclua o fluxo de autenticação, você pode obter as informações da organização do idToken
:
// Use JavaScript como exemplo
const idToken = await logto.getIdTokenClaims();
console.log(idToken.organizations); // Um array de strings com IDs de organização
O campo organizations
(reivindicação) também será incluído na resposta do endpoint UserInfo.
Opcional: Obter papéis da organização
Se você ainda não configurou papéis da organização, consulte esta seção.
Para obter todos os papéis da organização do usuário atual:
- Se você estiver usando um Logto SDK com suporte a Organizações, pode adicionar o escopo
urn:logto:scope:organization_roles
ao parâmetroscopes
do objeto de configuração. Normalmente, o SDK terá um enum para esse escopo, por exemplo,UserScope.OrganizationRoles
nos Logto JS SDKs. - Para outros casos, você precisa adicionar o escopo
urn:logto:scope:organization_roles
ao parâmetroscope
da configuração do SDK (ou solicitação de autenticação).
Então você pode obter os papéis da organização do idToken
:
// Use JavaScript como exemplo
const idToken = await logto.getIdTokenClaims();
console.log(idToken.organization_roles); // Um array de strings com papéis da organização
Cada string no array está no formato organization_id:role_id
, por exemplo, org_123:admin
significa que o usuário tem o papel admin
na organização com ID org_123
.
O campo organization_roles
(reivindicação) também será incluído na resposta do endpoint UserInfo.
Passo 2. Buscar token de organização
Para realizar ações no contexto de uma organização, o usuário precisa receber um token de acesso para essa organização (token de organização). O token de organização é um token JWT que contém o ID da organização e as permissões (escopos) do usuário na organização.
Adicionar parâmetros à solicitação de autenticação
- Se você estiver usando um Logto SDK com suporte a Organizações, pode adicionar o escopo
urn:logto:scope:organizations
ao parâmetroscopes
do objeto de configuração, da mesma forma que Obter IDs de organização do usuário atual.- O Logto SDK com suporte a Organizações cuidará automaticamente do restante da configuração.
- Para outros casos, você precisa adicionar os escopos
offline_access
eurn:logto:scope:organizations
ao parâmetroscope
e o recursourn:logto:resource:organizations
ao parâmetroresource
da configuração do SDK (ou solicitação de autenticação).- Nota:
offline_access
é necessário para obter orefresh_token
que pode ser usado para buscar tokens de organização.
- Nota:
// Apenas para outros casos. Para Logto SDKs, veja acima.
const config = {
// ...
scope: 'openid offline_access urn:logto:scope:organizations',
resource: 'urn:logto:resource:organizations',
};
O recurso urn:logto:resource:organizations
é um recurso especial que representa o modelo de organização.
Buscar o token de organização
Logto estende o tipo de concessão refresh_token
padrão para permitir que seu aplicativo busque tokens de organização.
- Se você estiver usando um Logto SDK com suporte a Organizações, pode chamar o método
getOrganizationToken()
(ou o métodogetOrganizationTokenClaims()
) do SDK. - Para outros casos, você precisa chamar o endpoint de token com os seguintes parâmetros:
grant_type
:refresh_token
.client_id
: O ID do aplicativo que o usuário usou para autenticar.refresh_token
: Orefresh_token
que você obteve do fluxo de autenticação.organization_id
: O ID da organização para a qual você deseja obter o token.scope
(opcional): Os escopos que você deseja conceder ao usuário na organização. Se não especificado, o servidor de autorização tentará conceder os mesmos escopos do fluxo de autenticação.
- JavaScript
- React
- Python
- PHP
- Swift
- Outros
const token = await logto.getOrganizationToken('<organization-id>');
const App = () => {
const { getOrganizationToken } = useLogto();
const getToken = async () => {
const token = await getOrganizationToken('<organization-id>');
};
return <button onClick={getToken}>Get organization token</button>;
};
token = await client.getOrganizationToken("<organization-id>")
# ou
claims = await client.getOrganizationTokenClaims("<organization-id>")
$token = $client->getOrganizationToken('<organization-id>');
// ou
$claims = $client->getOrganizationTokenClaims('<organization-id>');
let token = try await client.getOrganizationToken(forId: "<organization-id>")
// Use JavaScript como exemplo
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('client_id', 'YOUR_CLIENT_ID');
params.append('refresh_token', 'REFRESH_TOKEN');
params.append('organization_id', 'org_123');
const response = await fetch('https://YOUR_LOGTO_ENDPOINT/oidc/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params,
});
A resposta estará no mesmo formato do endpoint de token padrão, e o access_token
é o token de organização no formato JWT.
Além das reivindicações regulares de um token de acesso, o token de organização também contém as seguintes reivindicações:
aud
: O público do token de organização éurn:logto:organization:{organization_id}
.scope
: Os escopos concedidos ao usuário na organização com espaço como delimitador.
Exemplo
Um bom exemplo pode valer mais que mil palavras. Suponha que nosso modelo de organização tenha a seguinte configuração:
- Permissões:
read:logs
,write:logs
,read:users
,write:users
. - Papéis:
admin
,member
.- O papel
admin
tem todas as permissões. - O papel
member
tem permissõesread:logs
eread:users
.
- O papel
E o usuário tem a seguinte configuração:
- IDs de organização:
org_1
,org_2
. - Papéis da organização:
org_1:admin
,org_2:member
.
Na configuração do Logto SDK (ou solicitação de autenticação), configuramos outras coisas corretamente e adicionamos os seguintes escopos:
urn:logto:scope:organizations
openid
offline_access
read:logs
write:logs
Agora, quando o usuário conclui o fluxo de autenticação, podemos obter os IDs de organização do idToken
:
// Use JavaScript como exemplo
const idToken = await logto.getIdTokenClaims();
console.log(idToken.organizations); // ['org_1', 'org_2']
Se quisermos obter os tokens de organização:
// Use JavaScript como exemplo
const org1Token = await logto.getOrganizationTokenClaims('org_1');
const org2Token = await logto.getOrganizationTokenClaims('org_2');
console.log(org1Token.aud); // 'urn:logto:organization:org_1'
console.log(org1Token.scope); // 'read:logs write:logs'
console.log(org2Token.aud); // 'urn:logto:organization:org_2'
console.log(org2Token.scope); // 'read:logs'
const org3Token = await logto.getOrganizationTokenClaims('org_3'); // Erro: Usuário não é membro da organização
Explicação:
- Para
org_1
, o usuário tem o papeladmin
, então o token de organização deve ter todas as permissões disponíveis (escopos). - Para
org_2
, o usuário tem o papelmember
, então o token de organização deve ter permissõesread:logs
eread:users
(escopos).
Como solicitamos apenas os escopos read:logs
e write:logs
no fluxo de autenticação, os tokens de organização foram "reduzidos" de acordo, resultando na interseção dos escopos solicitados e os escopos disponíveis.
Buscar token de organização para um aplicativo máquina para máquina
Semelhante a buscar tokens de organização para usuários, você também pode buscar tokens de organização para aplicativos máquina para máquina. A única diferença é que você precisa usar o tipo de concessão client_credentials
em vez do tipo de concessão refresh_token
.
Para saber mais sobre aplicativos máquina para máquina, veja Máquina para máquina: Autenticação com Logto.
Passo 3. Verificar tokens de organização
Uma vez que o aplicativo obtém um token de organização, ele pode usar o token da mesma forma que um token de acesso regular, por exemplo, chamar as APIs com o token no cabeçalho Authorization
no formato Bearer {token}
.
Na sua API, a maneira de verificar o token de organização é bastante semelhante a Proteger sua API. Principais diferenças:
- Ao contrário dos tokens de acesso para recursos de API, um usuário NÃO PODE obter um token de organização se não for membro da organização.
- O público do token de organização é
urn:logto:organization:{organization_id}
. - Para certas permissões (escopos), você precisa verificar a reivindicação
scope
do token de organização dividindo a string com espaço como delimitador.