Access token for NodeJS application

api
nodejs

#1

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


#2

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:

#3

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


#4

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?


#5

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


#6

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?


#7

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.


#8

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.


#9

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?


#10

Hi @bdemers,

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


#11

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


#12

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)?


#13

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 ?


#14

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


#15

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


#16

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.