Refactoring Auth system to use Okta

Hello,

I have been asked to refactor the authentication system on an API we are using for a Single Page Application. I can get the middleware up and running and functional on the API side, but am unable to figure out exactly how this connects to the Front End. The login page makes a POST to the API, but its not clear to me how the token is returned.

Originally, the API used PassportJS and Oauth2, fetching user creds and privileges from the API’s database, with oauth-middleware to protect the routes.

I am new to anything Auth related and this is exceptionally confusing. Any help is greatly appreciated!

Hi @benawawa

There are two steps that need to be done through API: user authentication and user authorization.

#1 User authentication
An authentication, as per documentation available here, requires an HTTP POST Request to /api/v1/authn endpoint. Here is an example of a successful authentication:

Request

curl -v -X POST \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
  "username": "dade.murphy@example.com",
  "password": "correcthorsebatterystaple",
  "options": {
    "multiOptionalFactorEnroll": false,
    "warnBeforePasswordExpired": false
  }
}' "https://dragos.okta.com/api/v1/authn"

Response

{
  "expiresAt": "2015-11-03T10:15:57.000Z",
  "status": "SUCCESS",
  "sessionToken": "00Fpzf4en68pCXTsMjcX8JPMctzN2Wiw4LDOBL_9pe",
  "_embedded": {
    "user": {
      "id": "00ub0oNGTSWTBKOLGLNR",
      "passwordChanged": "2015-09-08T20:14:45.000Z",
      "profile": {
        "login": "dade.murphy@example.com",
        "firstName": "Dade",
        "lastName": "Murphy",
        "locale": "en_US",
        "timeZone": "America/Los_Angeles"
      }
    }
  }
}

#1.1 Handling MFA_REQUIRED status
If the user has set MFA, then he will need to pass the MFA Challenge. You can find here further documentation on how to verify each MFA factor.
Here is an example of a successful login request and Okta verify MFA pass (note that stateToken is generated in the beginning and has to be passed in each request until status in SUCCESS):

Request

curl -X POST \
  https://dragos.okta.com/api/v1/authn \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "exampleuser@mailinator.com",
  "password": "Test123!",
  "options": {
    "multiOptionalFactorEnroll": true,
    "warnBeforePasswordExpired": true
  }
}'

Response

{
    "stateToken": "00MSND_nTcSyf__qWHDGrEYM4pntKdaVzYmPLlVHGl",
    "expiresAt": "2018-10-18T09:14:45.000Z",
    "status": "MFA_REQUIRED",
    "_embedded": {
        "user": {
            "id": "00u2c5llocRHDiw8W2p7",
            "passwordChanged": "2018-10-18T08:18:55.000Z",
            "profile": {
                "login": "exampleuser@mailinator.com",
                "firstName": "Example",
                "lastName": "User",
                "locale": "en",
                "timeZone": "America/Los_Angeles"
            }
        },
        "factors": [
            {
                "id": "opf2c5m445atlLVQv2p7",
                "factorType": "push",
                "provider": "OKTA",
                "vendorName": "OKTA",
        ...........

Request

curl -X POST \
  https://dragos.okta.com/api/v1/authn/factors/opf2c5m445atlLVQv2p7/verify \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "stateToken": "00MSND_nTcSyf__qWHDGrEYM4pntKdaVzYmPLlVHGl",
}'

At this point, the MFA (Okta Verify) is pushed to the phone and has to be approved. If customer doesn’t have push option configured, you can ask him for the 6 digits code and send them as follows:

Request

curl -X POST \
  https://dragos.okta.com/api/v1/authn/factors/opf2c5m445atlLVQv2p7/verify \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "stateToken": "00MSND_nTcSyf__qWHDGrEYM4pntKdaVzYmPLlVHGl",
  "passCode": "228944"
}'

Response

{
    "expiresAt": "2018-10-18T09:21:39.000Z",
    "status": "SUCCESS",
    "sessionToken": "20111I8MsM2r6u4sjn4HfEtDXcDlHAdFYF8gOykGp-4xQnNIl1aT4Dy",
    "_embedded": {
        "user": {
            "id": "00u2c5llocRHDiw8W2p7",
            "passwordChanged": "2018-10-18T08:18:55.000Z",
            "profile": {
                "login": "exampleuser@mailinator.com",
                "firstName": "Example",
                "lastName": "User",
                "locale": "en",
                "timeZone": "America/Los_Angeles"
            }
        }
    }
}

#2 Using sessionToken
Once you retrieve the session token, you will need to pass it as a query parameter to the /authorize endpoint, as exemplified here and fully redirect the user to Okta (alternatively you can use postMessage() as shown here).

This request to the /authorize endpoint will authenticate the user (using the sessionToken) and then request an authorization code (if using authorization code flow with PKCE) or directly the tokens (if using implicit flow).


To get familiar with the authentication API, I recommend checking the Authentication API Postman collection available here.

1 Like