Is there a way to configure OIDC and API calls using private keys for client authentication in one Okta application? It seems, that OIDC cannot work with private keys (only with client secrets) and for API call just the client secret is not enough?
Background: I have a Node.js app + JS web frontend, where users should login via Okta and where the users list should be shown in the admin panel. For the first task, I successfully set up an application in Okta with Client authentication set to Client secret and use an OIDC compatible client. For the second, I set up another Okta application with Client authentication set to Public key / Private key and use the Okta Node.js SDK client. That works, but I wonder, if both tasks could be configured in just one Okta application?
I’m a little confused by your question, so I have a couple of my own to clarify this. Are you trying to authenticate using an OIDC flow or using the API from the SDK (or the sign-in widget on the client side)? And are we discussing a server-side or client-side application that needs to use the API? To explain what I am asking:
OIDC authentication flows should use the client ID, and either the client secret if it’s a server-side app or PKCE if it’s a client-side or native app. That’s how OIDC works, either a client secret or PKCE, it doesn’t use a public/private key.
Now, the API is a different story. You can use the Okta authentication API with either a secret or a public/private key to identity the app. That is analogous to a program using a database or something to verify identity, except in this case you are asking the Okta API to do it.
But for using the other Okta APIs to do things like getting a list of users in the organization requires that you either use an API token (a secret) to authenticate the application to the APIs, or you use an access token (issued through the OIDC flow) to talk to the APIs on behalf of an authenticated user. API tokens only work for server-side applications; for a client-side application you must you an access token.
So I think that you have more than one thing going on in your question? Let me know how else I can help.
We have a server-side application. The OIDC flow is implemented by creating the Okta authorizationUrl on the server by using the clientId and clientSecret, redirecting to user in the frontend to this URL, and then use the received code to authenticate the user in the server app (+ create a user in our app etc.). This runs well.
The second task we want to achieve is to retrieve the users list from Okta on the server. But how to receive an access token? The documentation of the Okta Node.js SDK only mentions authentication with an API token or a public/private key. Is there a Node.js SDK server-side possibility to authenticate against the API by using a client secret or, if I have already an authenticated user, to use the access token of a user?
Well, the API token is really a client secret for an application to talk to the Okta APIs. The API token has the privileges of the administrator user that issued it. It must be protected because it’s the only credential needed to make API calls and has those privileges, so that means a server-side application. If you are doing this from a nodejs application on a server, that would be the normal way to proceed. This token is issued in the interface via Security → API → Tokens.
If you are using auth-code flow in the server app to get the ID token for the user, you can also pick up the access token for using the Okta API there. The access token only has the rights of the user to do things, so you may or may not be able to list users, etc. What the access token allows is controlled by the application integration.
Ah, yes, with clientSecret I did not mean a general concept, but the secret we can use for an Okta application with “client credentials” authentication enabled (client ID + client secret). But this does not work with the Node.js SDK.
The problem with the API token is that it has only a life time of one month. Our customers do not want to generate a token every month.
Therefore, I would like to use the current user’s ID token to get an access token. However, there seems to be no way to do so with the Okta Node.js SDK, too. Only public/private key auth. That was my point. So, I fear, I will have to use the API endpoint directly and write my own requests.
Are you providing a different application instance for every customer, like a cloud-tenant?
Let me clarify the API token for you. The token doesn’t go to the customer, it belongs to the application running on the server. It has no expiration date, but it will expire if the application doesn’t connect to the API before thirty days is up. Even if the application doesn’t fire for some reason, an easy work-around for this is to have a scheduled job that makes an API call periodically.
Thanks a lot! It seems, I misunderstood the docs… I thought, that the API token is only valid for 30 days and did not see the “30 days from creation or last use” Sorry for the trouble! The work around is fine.
PS: About our work flow: Our app is used by many customers. And some want to integrate their Okta user data for OIDC login and for synchronizing their Okta users list with the one in our app. The customer admin will setup the configuration in our app, so he/she has to create the API token in Okta and save it in our app.
That is more understandable now, you are acting like a third-party vendor of tenants that allows use of their existing Okta org as the source of truth.
In that case I would really recommend using the access token even though it’s a server-side app. If you use the API token the app needs to make decisions about what each authenticated user is allowed to do. If you cache the access token in the user session, then the user’s rights in the Okta org control what they are allowed to do. On your side you need to request the correct scopes during the OIDC flow. The org owner would need to grant the scopes for the application integration: Applications → Applications → (some application) → Okta API Scopes
BTW, granted scopes doesn’t mean the user can do the task, it still needs to be something in their user account (like a profile change) or they have to have the appropriate admin role.
Thanks for the clarification! However, I guess we will need the API tokens, because the synchronization of user lists should be triggered not only by the customer admins, but also e.g. by me, who has no Okta account at the customer’s side.
So, the idea is that the customer admin configures the Okta integration in our app (saving an API token) and than all admins in our app (regardless if they have an Okta account or not) should be able to trigger the user list synchronization.
Cool! Salesforce recently shifted to using OIDC authentication for accessing their API, and in the application connector we configure that account to provision to SF.
I think the API token is still is the easiest, but an alternative worth mentioning would be similar: have a fallback account configured into the app that the app uses to get an access token for the local admin users.