# 4. Config Resource & Security info

**What you’ll do**: Define your app’s identity, API resources, and access permissions to establish how it securely interacts with Oten Platform. You’ll configure the client credentials (Client ID), define your app’s capabilities and scopes, and link integrations with other apps in the Oten ecosystem.

* Client Identity — client credentials for your application.
* App Capabilities & Security — your API model (permissions, features, scopes). Optional.
* Ecosystem Connections — connect other apps from the Oten platform and select the scopes you grant to each integration.

**Why it matters**: Properly configuring Resource & Security ensures your app is authenticated, authorized, and securely connected within the Oten ecosystem. This step protects user data, enforces permissions, and enables safe interoperability between your app and other Oten services or third-party integrations

**Steps:**

1. **Client Identity: Create a client**
   1. Open App Management → Configure Resources & Security → Client Identity.
   2. Create a client and choose a client type (see below).
   3. Save. You will receive a Client ID; server‑side apps also receive a Client Secret.
   4. Use this client in your app to run the standard Authorization Code flow (with PKCE when required).

**Client types:**

* Single Page Application (SPA — PKCE)
  * Use for browser‑based apps running entirely on the client.
  * Grant: Authorization Code with PKCE. No client secret (public client).
  * Required: at least one Redirect URI; configure Allowed Logout URL if you support logout.
  * Security notes: never store tokens in localStorage if you can avoid it; prefer HTTP‑only cookies via a backend for session management, or short‑lived Access Tokens with refresh via a secure channel.
* Regular Web Application (server‑side)
  * Use for apps that render on the server or have a backend that can keep secrets.
  * Confidential client: you will receive a Client Secret; keep it on the server only.
  * Grant: Authorization Code (no PKCE required, but PKCE is recommended when available).
  * Typical flow: browser → authorize → your server exchanges code for tokens → sets session.
* Native Application (mobile/desktop — PKCE)
  * Use for iOS/Android apps or desktop apps.
  * Grant: Authorization Code with PKCE. No client secret.
  * Redirect URI: use an app scheme (e.g., myapp\://callback) or a loopback URI (e.g., [http://127.0.0.1:PORT/callback](https://oten.gitbook.io/openplatform/about-us/user-guide/oten-developer/http:/127.0.0.1:PORT/callback)) as supported by your platform.

{% hint style="info" %}
**Quick Selection Guide**

* Have a backend server? → **Web Application**
* Browser-only app? → **Single Page Application**
* Mobile app? → **Mobile Application**
* Service-to-service? → **Machine-to-Machine**
  {% endhint %}

**Using your client: login, logout, profile:**

* Login
  1. Redirect the user to the Authorization Endpoint with response\_type=code, your Client ID, Redirect URI, requested scopes, and a code\_challenge (PKCE when required).
  2. Receive the authorization code at your Redirect URI.
  3. Exchange the code for tokens at the Token Endpoint (add code\_verifier for PKCE).
* Logout
  * Clear the local session and redirect the user to the configured logout endpoint (if your tenant exposes one) with a post‑logout redirect URI that matches the allowed list.
* Get profile
  * Call the UserInfo endpoint (or decode the ID Token) using the Access Token obtained above. Request the appropriate scopes (e.g., openid, profile, email) during login.

2. &#x20;**App Capabilities & Security (optional — Oten IAM)**

{% hint style="info" %}
If you want Oten to manage and enforce access to your APIs, declare a Resource Server. This step is optional and can be skipped if you do not need Oten IAM for your APIs.
{% endhint %}

**Step 1** — **Define the resource server**

The resource server represents your API or backend system in Oten. It becomes the audience that appears in access tokens.

<figure><img src="https://gitlab.silvertiger.tech/documents/open-platform/-/blob/document/.gitbook/assets/image%20(18).png" alt=""><figcaption></figcaption></figure>

Fields (as shown in the Add Resource dialog):

<table><thead><tr><th width="124.92578125">Field</th><th width="96.51953125">Required</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>Identifier</td><td>Yes</td><td>Unique URI/URN for your API. Appears as the aud claim in access tokens.</td><td>https://api.example.com, urn:oten:resource:my‑service</td></tr><tr><td>Name</td><td>Yes</td><td>Human‑readable name.</td><td>Orders API</td></tr><tr><td>Base URL</td><td>No</td><td>Base address of your API (used for documentation and discovery).</td><td>https://api.example.com</td></tr><tr><td>Description</td><td>No</td><td>Short description of what this API does.</td><td>Manage orders</td></tr><tr><td>Server type</td><td>No</td><td>Type of backend (REST, GraphQL, gRPC).</td><td>REST</td></tr><tr><td>Version</td><td>No</td><td>Semantic version label.</td><td>v1</td></tr><tr><td>Environment</td><td>No</td><td>Environment tag.</td><td>dev, staging, prod</td></tr><tr><td>Allowed issuers</td><td>No</td><td>Trusted identity issuers. Tokens must come from one of these.</td><td>https://auth.example.com</td></tr><tr><td>Tags</td><td>No</td><td>Free‑form labels to help search and group.</td><td>api, production, backend</td></tr><tr><td>Metadata</td><td>No</td><td>Additional structured info.</td><td>JSON blob</td></tr></tbody></table>

Best practice:

* Choose a stable Identifier and do not reuse it across different environments; use one per environment when needed.
* Keep Allowed issuers in sync with the identity domain that issues tokens for your app.

**Step 2** — **Define permissions (API level)**

Use permissions to tell Oten which HTTP methods and paths in your API are allowed.

This step covers API permissions created in the UI. If you need to protect screens/routes in your app UI, see Roles.

Fields (Add Permission dialog):

<table><thead><tr><th width="113.93359375">Field</th><th width="87.7578125">Required</th><th width="300.39453125">Description</th><th>Example</th></tr></thead><tbody><tr><td>Code</td><td>Yes</td><td>Unique identifier for the permission in your app. Use lowercase, numbers, dot or hyphen; no spaces.</td><td>games.read, users-manage</td></tr><tr><td>Name</td><td>Yes</td><td>Human-readable name shown in the console and consent screens.</td><td>View games</td></tr><tr><td>Type</td><td>Yes</td><td>Choose API permission (backend).</td><td>API</td></tr><tr><td>API operations</td><td>Yes</td><td>One or more operations this permission grants, each as Method + Path. Wildcard <code>*</code> matches subpaths.</td><td>GET /api/v1/games, GET /api/v1/games/*</td></tr></tbody></table>

How to add API operations

* Click Add row, pick the HTTP method (GET, POST, PUT, PATCH, DELETE).
* Enter the path exactly as your API exposes it (e.g., `/api/v1/games`).
* Use `*` to include subroutes (e.g., `/api/v1/games/*`).
* Add multiple rows if the permission should cover more than one operation.

<figure><img src="https://gitlab.silvertiger.tech/documents/open-platform/-/blob/document/.gitbook/assets/image%20(19).png" alt=""><figcaption></figcaption></figure>

Example

* Name: “View games list”
* Code: `games.read`
* API operations: `GET /api/v1/games` (optionally `GET /api/v1/games/*`) When a request hits those endpoints, Oten checks the caller has `games.read`.

Tips and rules

* Keep Code stable; treat it as an internal identifier (avoid renaming after publish).
* Code must be unique in your app and use only letters, digits, dot, underscore or hyphen; no spaces.
* Prefer least privilege: separate read vs write, admin vs user operations.
* Group multiple endpoints under one permission only when they represent the same capability.

**Step 3 — Privileges**&#x20;

Features are bundles of permissions that represent a capability in your product (e.g., “View games”, “Manage orders”). Users don’t assign permissions directly; they get them through Roles that include Features.

<figure><img src="https://gitlab.silvertiger.tech/documents/open-platform/-/blob/document/.gitbook/assets/image%20(20).png" alt=""><figcaption></figcaption></figure>

Fields (Privilege dialog):

<table><thead><tr><th width="117.5078125">Field</th><th width="92.62890625">Required</th><th width="284.73828125">Description</th><th>Example</th></tr></thead><tbody><tr><td>Code</td><td>Yes</td><td>Unique identifier for the feature in your app; use lowercase, numbers, dot or hyphen; no spaces.</td><td>games.readonly, orders-manage</td></tr><tr><td>Name</td><td>Yes</td><td>Human‑readable name shown in the console.</td><td>Games: Read only</td></tr><tr><td>Description</td><td>No</td><td>Optional explanation to help admins understand the feature.</td><td>Read game listings and details</td></tr><tr><td>Permissions</td><td>Yes</td><td>Select one or more previously defined permissions that this feature should grant.</td><td>games.read, games.write</td></tr></tbody></table>

How to create a feature

1. Click Add Privilege.
2. Enter Name and Code; optionally add a Description.
3. Click Add permission and select one or more permissions that represent the capability.
4. Save.

Examples

* “Games: Read only” → permissions: games.read
* “Games: Manage” → permissions: games.read, games.write
* “Orders: Admin” → permissions: orders.read, orders.create, orders.update, orders.delete

Tips and rules

* Keep features focused on a single capability so admins can compose roles cleanly.
* Reuse features across roles; avoid creating near‑duplicate features.
* Choose clear names (prefix by domain), e.g., “Games: Read”, “Games: Manage”, “Orders: Refunds”.
* Changing a feature changes all roles that include it; prefer adding new features over repurposing existing ones.

How privilege work with roles

* In the Roles tab, you attach privilege to a Role.
* Users/groups assigned that Role automatically inherit all permissions from the attached Features.

Automated Role Provisioning

When a developer adds a new Privilege, the platform automatically provisions a corresponding default access role. This role is instantly granted to two primary entities: The Personal Account user (upon account creation) and the Workspace Admin (upon application subscription). This mechanism streamlines the onboarding process, allowing them to access the application immediately without requiring subsequent self-permissioning steps.

**Step 4 — Define scopes (for cross‑app access and consent)**

Scopes represent what another application can access on behalf of a user or a client. A scope can map to:

* A set of API operations, or
* One or more permissions you defined in Step 2

When an external app requests access, the consent screen will present the scopes you expose. On approval, access tokens will include the granted scopes; Oten verifies scopes and routes access only to the APIs covered by those scopes.

Naming tips:

* Use a clear, namespaced format (e.g., games.read, chat.write, reporting.export).
* Keep scopes stable and backward‑compatible; add new scopes rather than repurposing existing ones.

3. &#x20;**Ecosystem Connection**

Use Integrate to expand your app by connecting to other applications on the Oten platform and granting them scoped access.

<figure><img src="https://gitlab.silvertiger.tech/documents/open-platform/-/blob/document/.gitbook/assets/image%20(21).png" alt=""><figcaption></figcaption></figure>

Steps:

1. Open the Integrate tab and click Add Integrate App.
2. Search for the provider application and switch it On.
3. Under “Select scopes to integrate with this application”, choose the scopes you want to grant.
4. Save.

Notes:

* Only apps that expose scopes (via their Resource Server → Scopes) will have selectable scopes. Otherwise you will see “No scopes available for this app”.
* Turning an app Off revokes future access; existing tokens may continue to work until they expire.
* When initiating OAuth with that provider, request the selected scopes. Users/org admins will review and consent to these scopes.

## How enforcement works (high level)

1. Your app authenticates the user and obtains an Access Token.
2. The token carries issuer (iss), audience (aud = your resource server Identifier), scopes, and/or permissions.
3. When the API is called, Oten IAM checks that:
   * The token’s issuer is in Allowed issuers.
   * The audience matches your resource server Identifier.
   * The requested operation is allowed by the token’s scopes/permissions.

## Troubleshooting

* invalid\_redirect\_uri: ensure your Redirect URI exactly matches one of the allowed URIs.
* invalid\_grant or PKCE errors: verify code\_verifier and code\_challenge pairing and that you exchange the code only once.
* mismatched\_issuer: add the correct issuer base URL to Allowed issuers on the resource server.
* insufficient\_scope: request or grant the scope/feature/permission that covers the API you are calling.

## Next steps

* Test the login flow with your chosen client type.
* If you registered a resource server, call your API with a token that has the required audience and scopes; confirm Oten allows/denies as expected.
* In Integrate, enable a provider app and select scopes; run a consent flow and verify the granted scopes appear in the token and permit only the intended APIs.
* In Roles, assign a role to a test user and verify features linked to that role gate functionality correctly.
* Continue to “Test your app” or “Publish your app” once authentication and authorization work end‑to‑end.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://oten.gitbook.io/openplatform/about-us/user-guide/oten-developer/4.-config-resource-and-security-info.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
