You can use the Gloo Portal Backstage backend plugin to integrate your API products into the Backstage catalog. Then, you can use your APIs as part of Backstage, such as to bundle your API products with other APIs in the Backstage catalog to create your own customized developer portal.

Before you begin

  1. Make sure that the external auth service is installed and running. If not, install the external auth service in your environment by installing Gloo Gateway Enterprise.
      kubectl get pods -A -l gloo=extauth
      
  2. Create the backend portal, to create and expose the portal server securely. Skip the frontend portal steps in that tutorial, which uses the sample React app.
  3. Store the URL to your developer portal app as an environment variable. The following example uses https://developer.example.com.
      export PORTAL_URL=https://developer.example.com
      
  4. Decide on the OpenID Connect (OIDC) provider that you want to use, such as Keycloak or Okta. This guide uses Okta as an example. If you don’t have an Okta account, sign up for an Okta developer account. For other examples, review the OIDC and OAuth guides.

Step 1: Set up an Okta OIDC app

Configure an Okta OIDC app to get the client and issuer information that you need to create external auth policies.

  1. Open the Okta dashboard. If you don’t have an Okta account that you can use, sign up for an Okta developer account.

  2. From the Applications menu, click Applications > Create New App. Note that you might see a Create App Integration button instead.

    Figure: Okta application dashboard
    Figure: Okta application dashboard
  3. Select OIDC - OpenID Connect as the sign-in method for your app and Web application as your application type. Then, click Next.

  4. Enter a name for your app and optionally upload a logo.

  5. For Grant type, select Client Credentials, Authorization Code, and Refresh Token.

  6. For Sign-in redirect URIs, enter the location from which you want to allow users to log in. The URL is composed of the hostname that you set up for your Portal resources and the /callback path. For example, for the developer portal frontend app, you might enter https://developer.example.com/callback.

  7. For the Sign-out redirect URIs, enter the location to redirect the user after logging out, such as https://developer.example.com/logout.

  8. From the Assignments section, select Allow everyone in your organization to access. This way, you do not need to assign a user or group to this app. Instead, you can use your Okta developer account credentials to test the Okta authentication flow.

  9. Click Save to save your changes. You are redirected to the Okta app details page.

  10. From the General tab on the Okta app details page, note the Client ID and the client Secret.

    Figure: Okta General tab
    Figure: Okta General tab
  11. Store the Client ID and Secret as environment variables.

      export CLIENT_ID=<client-id>
    export CLIENT_SECRET=<secret>
      
  12. From the Sign on tab in the OpenID Connect ID Token section, change the Issuer from Dynamic to the Okta URL. Your Okta URL typically includes your account ID and an okta.com extension, such as https://dev-12345678.okta.com.

    Figure: Okta Signon tab
    Figure: Okta Signon tab
  13. Store the issuer URL as an environment variable.

      export ISSUER_URL=<issuer-URL>
      
  14. From the navigation menu, click Security > API.

  15. Click the Authorization Server that you want to use, such as default.

  16. From the Settings tab, click the Metadata URI. In a new tab, your browser opens to a URL similar to https://dev-1234567.okta.com/oauth2/default/.well-known/oauth-authorization-server.

  17. From the metadata URI, search for and save the token_endpoint as an environment variable. This endpoint is where to get the OAuth token.

      export TOKEN_ENDPOINT=https://dev-1234567.okta.com/oauth2/default/v1/token
      

Step 2: Set up OAuth external auth for your portal

Set up Gloo Gateway external auth policies with Okta as the OIDC provider.

  1. Create a Kubernetes secret with the client secret from your Okta account.

      kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Secret
    type: extauth.solo.io/oauth
    metadata:
      name: okta-client-secret
      namespace: gloo-system
    stringData:
      client-secret: ${CLIENT_SECRET}
    EOF
      
  2. Create an AuthConfig resource to enforce authentication to your developer portal routes via an authorization code from the Okta OIDC provider that you set up.

      kubectl apply -f- <<EOF
    apiVersion: enterprise.gloo.solo.io/v1
    kind: AuthConfig 
    metadata: 
      name: okta-portal-auth-code 
      namespace: gloo-system
    spec: 
      configs: 
      - oauth2: 
          oidcAuthorizationCode: 
            appUrl: '$PORTAL_URL' 
            callbackPath: /callback 
            clientId: '$CLIENT_ID'
            clientSecretRef: 
              name: okta-client-secret 
              namespace: gloo-system 
            issuerUrl: '$ISSUER_URL'
            scopes: 
            - openid 
    EOF
      

    Review the following table to understand this configuration.

    SettingDescription
    appUrlEnter the address to access the developer portal app. If you followed the example in this guide, your app URL is https://example.developer.com.
    callbackPathCreate the redirect URL by appending this path to the appUrl. After successful authentication in Okta, you are redirected to this URL.
    clientIdEnter the client ID that was assigned to your Okta OIDC app. You can retrieve the client ID from the General tab of your Okta OIDC app.
    clientSecretEnter the reference to the Kubernetes secret that you created earlier and that stores the client secret value. You can retrieve the client secret from the General tab of your Okta OIDC app.
    issuerUrlEnter the Okta issuer URL that you set up in the Okta app, such as https://dev-12345678.okta.com. You can retrieve the Okta issuer URL from the Issuer field on the Sign on tab of your Okta OIDC app.
  3. Create a RouteOption resource that refers to the AuthConfig resource.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata:
      name: okta-portal-auth-code
      namespace: gloo-system
    spec:
      options:
        extauth:
          configRef:
            name: okta-portal-auth-code
            namespace: gloo-system
    EOF
      
  4. Create or update the HTTPRoute for the frontend developer portal to require authentication with Okta.

      kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: portal-frontend-route
      namespace: gloo-system
    spec:
      parentRefs:
        - name: http
          namespace: gloo-system
      hostnames:
        - portal.example.com
      rules:
        - backendRefs:
            - name: portal-frontend
              namespace: gloo-system
              port: 4000
          filters:
            - type: ExtensionRef
              extensionRef:
                group: gateway.solo.io
                kind: RouteOption
                name: okta-portal-auth-code
    EOF
      
  5. Verify that your resources are in an Accepted state. If not, review the messages. Common issues include referencing the wrong RouteOption resource in the extensionRef filter, creating multiple RouteOption resources and attaching them via the targetRefs option, or missing ReferenceGrants for resources that are in different namespaces.

      kubectl describe AuthConfig -n gloo-system okta-portal-auth-code
    kubectl describe RouteOption -n gloo-system okta-portal-auth-code
    kubectl describe HttpRoute -n gloo-system portal-frontend-route
      

Step 3: Install the Gloo Portal Backstage backend plugin

Install the backend plugin for your developer portal in your Backstage application. The following steps show how you can add the backend plugin to an existing Backstage application. You can also use a sample container image in Solo’s public image registry, gcr.io/solo-public/docs/portal-backstage-backend.

The plugin creates the following Backstage catalog entities and relates them to each other:

  • A Group with the name solo-io-service-accounts.
  • A User with the name gloo-platform-portal-service-account.
  • A System with the name gloo-platform-portal-apis.
  • An API for each apiVersion of each apiProduct in your Gloo Portal instance that the service account has access to. The API’s name is a combination of the apiProductId and the apiVersion (apiProductId-apiVersion).
  1. Create or use an existing Backstage app. If you do not have a Backstage app, follow the getting started guide to install one on your local machine.

      cd portal
      
  2. Install the Gloo Portal Backstage backend plugin into your Backstage app.

      yarn --cwd ./packages/backend add @solo.io/platform-portal-backstage-plugin-backend
      
  3. From the Backstage app root directory, open the /packages/backend/index.ts file.

      open packages/backend/src/index.ts
      
  4. Update and save the file to include the following Gloo Platform provider information.

      // -> 1. Replace the existing import:
    // import { createBackend } from '@backstage/backend-defaults';
    // with the import for the Gloo Platform plugin.
    import {
      coreServices,
      createBackendModule,
    } from '@backstage/backend-plugin-api';
    import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
    import { GlooPlatformPortalProvider } from '@solo.io/platform-portal-backstage-plugin-backend';
    
    // -> 2. Create the provider for the plugin.
    export const catalogGlooPlatformPortalBackendProvider = createBackendModule({
      pluginId: 'catalog',
      moduleId: 'gloo-platform-portal-backend-provider',
      register(env) {
        env.registerInit({
          deps: {
            catalog: catalogProcessingExtensionPoint,
            logger: coreServices.logger,
            config: coreServices.rootConfig,
            scheduler: coreServices.scheduler,
          },
          async init({ catalog, logger, config, scheduler }) {
            catalog.addEntityProvider(
              new GlooPlatformPortalProvider(logger, config, scheduler),
            );
          },
        });
      },
    });
    
    // -> 3. Leave the backend and other packages from the file.
    const backend = createBackend();
    // (truncated for brevity)
    // until the last Kubernetes backend
    backend.add(import('@backstage/plugin-kubernetes-backend/alpha'));
    
    // -> 4. Add the Gloo Platform provider to the backend.
    backend.add(catalogGlooPlatformPortalBackendProvider);
    
    // -> 5. Leave the backend start function from the file.
    backend.start();
      
  5. From the Backstage app root directory, open the app-config.local.yaml file.

      open app-config.local.yaml
      
  6. Configure the details of the OAuth identity provider that you use for external authentication to your Gloo Portal. Replace the $PORTAL_URL, $CLIENT_ID, $CLIENT_SECRET, and $TOKEN_ENDPOINT variables with the values that you previously retrieved. For more information, see the Okta step.

    Example command to get your OAuth details:

      echo $PORTAL_URL
    echo $CLIENT_ID
    echo $CLIENT_SECRET
    echo $TOKEN_ENDPOINT
      

    Example app-config.local.yaml file:

      # Backstage override configuration for your local development environment
    glooPlatformPortal:
      backend:
        # The URL of the Gloo Portal REST server.
        # Format this variable with a "/v1" path, such as: "https://developer.example.com/v1".
        portalServerUrl: "$PORTAL_URL/v1"
        # The OAuth identity provider's Client ID.
        # In Keycloak, open the $KEYCLOAK_URL UI, click Clients, and from the Settings tab, find the Client ID.
        # In Okta, open your $OKTA_URL and from the Applications section, find your app's Client ID.
        clientId: "$CLIENT_ID"
        # The OAuth identity provider's Client secret.
        # In Keycloak, open the $KEYCLOAK_URL UI, click Clients, and from the Settings tab, find the Client secret.
        # In Okta, open your $OKTA_URL and from the Applications section, find your app's Client secret.
        clientSecret: "$CLIENT_SECRET"
        # The endpoint to get the OAuth token.
        # In Okta or Keycloak, you can find the `token_endpoint` property at:
        # $KEYCLOAK_URL/auth/realms/<your-realm>/.well-known/openid-configuration
        # $OKTA_URL/.well-known/openid-configuration
        tokenEndpoint: "$TOKEN_ENDPOINT"
        # Optionally enable logging to troubleshoot issue
        # and disable for regular use cases
        debugLogging: false
        syncFrequency:
          hours: 0
          minutes: 1
          seconds: 0
          milliseconds: 0
        syncTimeout:
          hours: 0
          minutes: 0
          seconds: 10
          milliseconds: 0
      
  7. Open the Backstage app. The app opens on http://localhost:3000. It might take a few minutes to open and finish building.

      yarn dev
      
  8. From the menu, select APIs. Verify that you see your portal API products, such as petstore-v1 and tracks-v1.

    Figure: Backstage API catalog page
    Figure: Backstage API catalog page
  9. Click one of the APIs, such as tracks-v1, and explore the API.

You successfully installed and verified the Gloo Portal backend plugin for Backstage!

Next steps

You deployed the Backstage backend app to add the APIs from your developer portal to the Backstage API catalog. Now, when you update your Portal resource to add new API products, usage plans, or metadata, your APIs are automatically updated in the Backstage catalog for you.