Portal AuthN and AuthZ
Learn how you can secure access to the developer portal and the private APIs that it serves.
Securing the portal does not automatically secure access to your APIs. Make sure to apply external auth policies to your APIs as well.
About authentication and authorization
You can set up two primary types of security for the portal: external authentication and user authorization.
- External authentication: Require users to externally authenticate via an OpenID Connect (OIDC) provider when they send a request to a portal endpoint.
- User authorization with PortalGroups: Specify claims that must be present in the user’s JWT from the OIDC provider before the user gets access to a particular API.
External authentication with the developer portal
You can set up external authentication with a supported OpenID Connect (OIDC) provider to control access to the developer portal.
About OIDC
OIDC is an identity layer on top of the OAuth 2.0 protocol. In OAuth 2.0 flows, authentication is performed by an external Identity Provider (IdP) which, in case of success, returns an access token that represents the user’s identity.
The OAuth protocol does not define the contents and structure of the access token, which greatly reduces the portability of OAuth 2.0 implementations. The goal of OIDC is to address this ambiguity by additionally requiring Identity Providers to return a well-defined ID Token. OIDC ID tokens follow the JSON Web Token standard and contain specific fields, also referred to as claims, that you can use to verify access to specific app resources.
This standardization allows you to switch between Identity Providers, or support multiple ones at the same time with minimal or no changes to your services.
OIDC authentication for a developer portal
Without OIDC authentication, unauthenticated users can log in to the developer portal and create API keys for public APIs, view API schemas, get information about portal usage plans, or details about the current user’s session.
To protect your developer portal with an OIDC provider, you must decide on the developer portal APIs for which you want to require authentication. For example, you typically want to require authentication when logging in to the portal, creating API keys, or viewing a user’s session data. However, you might not require authentication to view usage plans.
OIDC authentication flow
The following image illustrates the authentication flow when logging in to the developer portal.
When a user tries to log in to the portal, the request is intercepted by the external auth server and redirected to the OIDC provider where the user must enter the credentials to get authenticated.
After successful authentication, an ID and refresh token are returned by the OIDC provider. You have the option to store these tokens in Redis and get back a Redis session ID, or to return the raw ID token in the Set-Cookie
response header. To prove successful authentication in subsequent requests, the user sends the ID token information in the Cookie
request header. If you have private API products that your portal serves, the ID token is forwarded to the portal server to extract the claims and find a matching portal group. For more information, see User authorization for private APIs with portal groups.
To learn how to set up authentication for your portal with an OIDC provider, see Set up external authentication.
Set up external authentication
For instructions, follow the Secure access to the portal tutorial.
User authorization for private APIs with portal groups
If your portal serves private APIs, you must configure authorization by using portal groups. A portal group specifies the claims that must be present in a JWT ID token to allow access to specific private APIs and usage plans, and to perform actions, such as to create API keys for these APIs. Therefore, portal groups create an additional layer of security for your portal alongside the external OIDC authentication.
To configure authorization for private APIs, you must set up authentication with an OIDC provider first. After successful authentication, the OIDC provider returns an ID token and refresh token. The ID token contains the claims that are used to match the user to a portal group. After a matching portal group is found, access to the private APIs and usage plans is granted.
The following image illustrates the authorization flow when trying to create an API key for a private API. Note that this flow assumes that the user is successfully authenticated with an OIDC provider and received an ID token.
Authorization for private APIs with portal groups helps you to configure the private APIs that a user can see when logging in to the developer portal. Authorized users can then view the API schema or create API keys to interact with the API. However, portal groups cannot be used to configure APIs to require API keys when interacting with the API. If you want to require API keys to be created for an API, see Prepare usage plans for your API products.
Create a portal group for authorization
To control access to private API products in your developer portal, you set up portal groups and specify the conditions that must be met to successfully authorize a user to see the private APIs.
To match a user with a portal group, the user must present an ID token from an OIDC provider. To learn how to integrate your developer portal with an OIDC provider, see Set up external authentication.
If you have not done yet, decide on the visibility setting for the API products that are included in the developer portal. For more information, see Set API product visibility. Note that authorization is required only for private APIs. If you decide to keep your APIs public, you do not need to set up portal groups.
Follow the Secure access to the portal tutorial. This step is required to receive the ID token from your OIDC provider and identify the claims that you want to use for your portal group.
Identify the claims in the ID token that you want to match on. Only if a user presents a token with the right claims, the user is matched with the portal group and is granted access to the private APIs and usage plans that you define in the portal group. The ID token is returned by the OIDC provider during authentication. Depending on the OIDC provider that you use, you can customize the claims that are being returned in the ID token. However, some OIDC provider might not allow you to create custom claims.
Your ID token might have a claim structure that is similar to the following:
{ "exp": 1681133278, "iat": 1681133218, "auth_time": 1681133218, "jti": "3e410301-d9a2-463f-a127-df78a94f87db", "iss": "http://34.xxx.xxx.xxx:8080/auth/realms/master", "aud": "4464fbac-ab29-4c6a-945b-14e4685c0ad4", "sub": "83a467a1-8f4e-4dd6-8fd1-34832ba0a84e", "typ": "ID", "azp": "4464fbac-ab29-4c6a-945b-14e4685c0ad4", "session_state": "aac7790f-036c-4367-b728-1f1d9dc355fe", "at_hash": "2nFLjyWQA2pEANc8zuhwTw", "acr": "1", "email_verified": false, "preferred_username": "user1", "email": "user1@example.com", "group": "users" }
Create a portal group to allow access to the petstore API product for a user that presents an ID token with the
group: users
claim.kubectl apply -f- <<EOF apiVersion: apimanagement.gloo.solo.io/v2 kind: PortalGroup metadata: name: petstore-group namespace: gloo-mesh spec: name: petstore-group description: A group that grants access to the petstore API and allows users in this group to manage API keys for the bronze, silver, and gold usage plans. membership: - claims: - key: group value: users accessLevel: apis: - labels: api: petstore EOF
Setting Description spec.membership.claims
Set the claims in the JWT ID token that must be present to successfully match the user with this portal group. Note that the claims that you specify must exist in the ID token that your OIDC provider returns. You have the option to specify one or multiple claim sets. In this example, the ID token must include the group: users
claim.spec.accessLevel.apis
Select the private API products that the user can view in the developer portal after the user is matched with this portal group. To select an API product, you use a label that exists on the route table that represents the API product. To give access to all private APIs, use the same label that you set for the portal visibility, such as portal-visibility: private
. For more information, see Add API products to the portalspec.accessLevel.usagePlans
Select the usage plans that the user has access to after the user is matched with this portal group. For more information, see Add usage plans. Send a request to the
/v1/apis
endpoint to list the APIs that you have access to. Note that in your CLI output, only the tracks API is listed. The private petstore API is hidden because no ID token with the right claims is presented in the curl request.curl -vik --resolve developer.example.com:80:$INGRESS_GW_IP http://developer.example.com:80/v1/apis
Example output:
[{"apiId":"tracks-rt-gloo-mesh-gateways-portal","contact":"support@example.com","customMetadata":null,"description":"REST API for Catstronauts to retrieve data for tracks, authors and modules.","license":"license info","termsOfService":"You must authenticate to use this API! And other Terms of Service.","title":"Catstronauts REST API","usagePlans":["silver","gold","bronze"]}]
Follow the steps in Verify external authentication to retrieve your ID token.
Send another request to the
/v1/apis
endpoint. This time, you provide the ID token that you retrieved in the previous step in theCookie
request header. In your CLI output, verify that you also see the petstore API, because now, you are successfully authenticated and authorized to see this private API.curl -vik -H "Cookie: ${ID_TOKEN}" --resolve developer.example.com:80:$INGRESS_GW_IP http://developer.example.com:80/v1/apis
Example output:
[{"apiId":"tracks-rt-gloo-mesh-gateways-portal","contact":"support@example.com","customMetadata":null,"description":"REST API for Catstronauts to retrieve data for tracks, authors and modules.","license":"license info","termsOfService":"You must authenticate to use this API! And other Terms of Service.","title":"Catstronauts REST API","usagePlans":["silver","gold","bronze"]}]