luigibertaco
luigibertaco

Reputation: 1132

What's the proper way to implement a "static" authorization token feature using OIDC (or OAuth2)

I am exploring possible solutions for creating something like "API Keys" to consume my API. The goal is to allow for users to generate one or many "API Keys" from the web app and use the static generated key from the CLI app.

The web app and the client app are already using standard OIDC with JWT tokens for authentication and authorization using RBAC (role-based access control). The CLI app can already authenticate the user through the standard browser flow (redirects the user to the browser to authenticate and exchange the token back to the client).

The "API Keys" solution I am trying to achieve should have some fine-grained options where it won't authenticate as the user, but will authorize the client on behalf of the user (something like the GitHub Personal Access Token).

To me it seems like a "solved problem" as multiple services provide this kind of feature and my goal is to do it the most standard way possible using the Oauth2/OIDC protocols but I can't find details on what parts of the protocols should be used.

Can anybody provide any guidance on how it is supposed to be done using the Oauth2/OIDC entities?

Can I achieve it by only using Role-based access control or do I need Resource-based access control?

It went through the path of creating a new client for each "API Key" created, but it didn't feel right to create so many clients in the realm.

Any guidance or links to any materials are appreciated.

Upvotes: 2

Views: 2372

Answers (2)

Gary Archer
Gary Archer

Reputation: 29208

To call your API in an OAuth way, CLI users must authenticate periodically. Resulting access tokens can be long lived, as for GitHub keys, if you judge that secure enough. The access token returned can be used exactly like an API key. There may be a little friction here between usability and security.

CONSOLE FLOW

The classic flow for a console app is to use the Native Apps Desktop Flow from RFC8252. This involves the user interactively signing in using the code flow, then receiving the response on a loopback URL. It is an interactive experience, but should only be required occasionally, as for GitHub tokens.

API KEYS

The access token returned is sent in the authorization header and you can use it as an API key. Access tokens can use a reference token format. to make them shorter and confidential, to prevent information disclosure. These will be more natural in a CLI.

API AUTHORIZATION

When your API is called, it must receive access tokens containing scopes and claims, to identify the user. This will enable you to authorize correctly and lock down permissions.

{
  sub: 586368,
  scope: repos_write,
  topic: mobile,
  subscription_level: silver
  exp: ?
}

TOKEN REFRESH

Sometimes CLI access tokens are long lived, for convenience. A more secure option is for the CLI to use token refresh. It can then store a refresh token in OS secure storage, then renew access tokens seamlessly. My blog post has some screenshots on how this looks, and a desktop app that does not require login upon restart. The CLI needs to deal with expired access tokens and handle 401 responses.

DYNAMIC CLIENT REGISTRATION

Some developer portal scenarios use DCR. It is another option in your security toolbox. It could potentially enable a silent client per CLI user:

  • User runs a standard authentication flow with a DCR scope
  • This returns an access token that enables client registration
  • The resulting token is used to register a new client
  • This could potentially be a client ID and client secret used in a CLI

Afterwards, the user and client are bound together. Probably not immediately relevant, but worth knowing about.

Upvotes: 0

MSZMC
MSZMC

Reputation: 154

Can anybody provide any guidance on how it is supposed to be done using the Oauth2/OIDC entities?

OIDC is based on OAUth 2.0 so after user login you have id tokens, access token and refresh token on the backend side. To generate new access token without asking user for authentication data you should use refresh token: https://oauth.net/2/refresh-tokens/

Can I achieve it by only using Role-based access control or do I need Resource-based access control?

resource-based access control is more flexible solution here, but if you business requirement is not complex, then role based might be enough.

It went through the path of creating a new client for each "API Key" created, but it didn't feel right to create so many clients in the realm.

It is one application so you should use one client with specific configuration for access token and roles/permissions for users.

Update: We can use GitHub as an example:

  1. User is authenticated during login
  • for OIDC code is exchanged for id token, access token and refresh token
  • session for user is set for web browser
  1. User can request access token
  • in GitHub authenticated user can request github.com/settings/personal-access-tokens/new endpoint
  • request is accepted, because user is authenticated based on session
  • backend service responsible for returning access token can obtain new access token using refresh token from point 1.
  • access token is returned to GitHub user

Upvotes: 1

Related Questions