Access token for NodeJS application

Hi Everynone,

We have a NodeJS API(Let’s call it ‘app1’), this application verify given access_token and allow other applications to access different routes.
We also have another NodeJS application(‘app2’), which needs to talk with app1, to do that app2 need a access_token.
Can you please help me how to get a access_token for my app2 ?

I am trying to use this endpoint (/api/v1/authn), pass ‘api_token’, username, password to get the session token. To get access_token I am trying to use this endpoint(/oauth2/default/v1/authorize). Then I will use this access_token to make calls to app1

Is this is right approach ?
Is this access_token expires at same time sessionToken expires ?

So do we really need a username/password for each application or we can get access_token using any other approach ?

With above approach we need to pass ‘redirect_uri’ to get access_token, to do that we need to start app2 then send a request to okta and get access_token. Because I can give current application url(/implicit/callback or something) as redirect_uri.
We have a requirement that we need to start app2 if it is able to talk with app1, so without passing redirect_url can I get access_token ?

I am new to OKTA, please let me know if you need more information.

Thanks,
JanakiRam

Hey @janakiram.gollapudi! Welcome to the forum!

It sounds like you shouldn’t be using the /authn API (we recommend using OAuth/OIDC whenever possible), but before I give any suggestions or advice, I have a couple questions for you.

  • Which applications have direct user interaction? It sounds like just app1?
  • Is app1 just a gateway that just handles auth delegates to other services (app2, app3, etc)?
  • How much trust does your application need? This might seems like an odd question, some API gateways basically just proxy the same access_tokens between services (for example Spring Zuul in the Java world does this). Other setups are a bit more complex :smiley:

Hi @bdemers,

Thanks for quick response.

  • Which applications have direct user interaction? It sounds like just app1 ?

    Actually we have angular application which has direct user interaction, this angular app also talks with ‘app1’ . Our angular application working fine and able to talk with okta and sends a ‘access_token’ to ‘app1’ and ‘app1’ verifies token. All good there. But ‘app2’ is a back-end application, with no UI, it is a micro service which needs to talk with ‘app1’ to do CURD operations on data.

  • Is app1 just a gateway that just handles auth delegates to other services (app2, app3, etc)?

    No. ‘app1’ verifies access_token, if token is valid then get data from DB and sends response.

  • How much trust does your application need? This might seems like an odd question, some API gateways basically just proxy the same access_tokens between services (for example Spring Zuul in the Java world does this). Other setups are a bit more complex :smiley:

    I am not completely understand this question. Yes we need proper trust for our back-end micro services like app2 , appx… which are talking with ‘app1’.

Please let me know if I miss anything.

Thanks,
JanakiRam

Sorry, I left a little out on that last part “how much trust”. Some gateways just proxy a token (think just another Bearer: token_here request. Some other setups require independent trust between the applications (another layer of oauth, certificates etc, and encode the original token differently). I don’t know of any off the shelf libs that do this outside of the Java world.

Back to your use case. I still not 100% on where the touch points are, please correct me if i’m wrong, you have:

front-app - Angular handles user interaction from browser
app1 - handles requests made from front-app, (requests are handled from a browser)
app2 - handles requests made from app1 (possibly on a back channel network not exposed to internet)

How am i doing?

Hi @bdemers,

No worries.

  • We have a front-app which talks with app1, you are right app1 handles requests made from front-app.
  • For every request app1 checks if request header has valid access token or not.
  • app2 is another micro service, this service listens for SQS message, if it receives a message from SQS then sends requests to app1. So app2 talk with app1.
  • So app2 need a access_token to send request to app1, so that app1 verifies access_token sent in request header.

Thanks,
JanakiRam

1 Like

A picture is worth a thousand words!

App1 is receiving tokens from two different applications a user-facing one (which is working), and your microservice.

It sounds like you should configure App1 to also allow the client credentials. Though you may want to set up a separate Okta application for this (to have a unique client id/secret).

I wrote a post on how to set up server-to-server communication, It uses Java + Spring, but the okta side configuration and principals are the same.

Does that help?

You are right App1 receiving tokens from two different applications. I will go through your post and get back to you.

Thanks for your response. Appreciate it.

Hi @bdemers,

It worked. Thank for your post. I am just adding steps that I did, so that it helps someone with similar problem in node app.

  1. First I created a new service application as you suggested in post and added a custom claim
  2. Then from app2 I sent a post request to this url “<base_url>/v1/token” with client_id, client_secret, grant_type, scope, I got access_token
request.post(`<base_url>/v1/token`, {
    form: {
      "client_id": "<newly created server application client id>",
      "client_secret": "<newly created server application client secret>",
      "grant_type": "client_credentials",
      "scope": "<newly added custom scope suggested in blog>"
    },
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    json: true
  }).then(async function (response) {
    let jwt = response.access_token;
  })
  .catch(function (err) {
  
  });  
  1. I used this access token for in all request to app1

Here I have two problem:

  1. My font app has different client_id(because I created a single page application in Okta) and my app2 has different client id(because I created a server application), but in app1 while verifying I need to use right client id, meaning if request comes from font app I should use single page application client id, if request comes from app2 then service application client id, then only verification passes.
  2. This access token expires after 1 hour, so we need to send a post request from app2 to okta to get new access token for every one hour. Please let me know if we can solve this with different approach ?

I am trying to solve these now.

1 Like

I’d always recommend using a client library to handle the oauth interaction. You can take a look at ours okta/okta-oidc-js and/or our getting started guide (for js)

You can use any OAuth lib though.

I mentioned this because refreshing the token should be handled automatically (along with the actual /v1/token request)

Does that help?

Hi @bdemers,

Thanks for the information. I will go through oidc-middleware package.

1 Like

Hi @bdemers

From front app OR from App2, We are passing access token to App1. In App1 we are verifying token.

oktaJwtVerifier.verifyAccessToken(accessToken)
.then((jwt) => {
 logger.info(jwt.claims.sub); 
}) 

In my Okta developer account, I have sub claim for default authorization server is like this:

(appuser != null) ? appuser.userName : app.clientId

So when we pass access token from App2, In App1 jwt.claims.sub returning Client ID instead of Username. Because appuser is null.
If I want to get username, after token verification, should I use Okta REST with api_token and userid(I need to stick with one user id) to get user information ?

Appreciate your help.

Thanks,
JanakiRam

What would the username be in this context? I thought it was a machine to machine connection (i.e. an end user is not involved)?

Right this is machine to machine connection.
We need user information with every API request, because we are using this user information while creating/updating records in DB. Font app and App2 are using same API endpoints(available on App1).

Is there a way to set user details for service application, so that I can access them once I verify access token ?
OR
Is it possible to use user credentials(We will store this user information in secure place) for every request coming from App2 ?

I guess you can use “Resource owner password flow” instead of “Client credentials flow”, which will allow you to associate a user with app2. See this - https://developer.okta.com/authentication-guide/auth-overview/#resource-owner-password-flow

Sure @vijet. Thanks for the response. I will try to use ‘Resource owner password flow’, will let you guys know the status.

I’d recommend you handle those tokens slightly different for your auditing purposes, that way you know the request was made outside the context of a real user.