RPort - remote access and remote management
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Developers Guide

Introduction

RPort OAuth has implemented support for sign-in via three of the main OAuth web identity providers (github, microsoft and google). This allows RPort users to sign-in with their credentials for these services.

While RPort is providing the technology, RPort administrators must setup and configured these services to enable use by rportd. For more information, see the Configuration Settings and the individual provider sections.

The sections below describe how to use the RPort APIs to sign in users via an OAuth provider and obtain an RPort JWT bearer token which can then be used to login to RPort.

As mentioned previously, the RPort APIs can be configured to use either an OAuth style web app or device flows, or both together.

Determine Provider and Settings URL

To determine which provider has been configured, the /auth/provider endpoint can be called.

curl -s "http://localhost:3000/api/v1/auth/provider" | jq

This will return a response similar to the below:

{
  "data": {
    "auth_provider": "github",
    "settings_uri": "/api/v1/auth/ext/settings",
    "device_settings_uri": "/api/v1/auth/ext/settings/device"
  }
}

The auth_provider value contains the OAuth provider in use. This can be used to let the user know which auth provider they will be signing in with.

The settings_uri indicates an endpoint which returns values required to proceed with an individual sign-in for a user via the web app style flow. Note that the settings_uri returns a state value with a limited lifetime. It is therefore highly recommended that the settings are obtained after the user has pressed a sign-in button.

The device_settings_uri indicates an endpoint which returns values required to proceed with a sign-in via the device style flow. Note that the device_settings_uri returns values per authorization, so must be called for each user sign-in.

User Sign-In - Web App Style Flow

To initiate the user sign-in after a login or similar button has been pressed, the /auth/ext/settings endpoint (as returned by the /auth/provider endpoint) must be called.

curl -s "http://localhost:3000/api/v1/auth/ext/settings" | jq

This will return a response similar to the below:

{
  "data": {
    "auth_provider": "github",
    "details": {
      "message": "Please authenticate on the authorize_url and submit via GET the code and state values returned by the auth provider to the login_uri",
      "authorize_url": "https://github.com/login/oauth/authorize?client_id=f10b0afd5e2edbbd4ed8&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth%2Fcallback&scope=read%3Aorg&state=AruY3s6MMcMS4K4bn2T2zBqG8dW9vDxq_OX6zTUqA_yfveX_mF5TJ7KeSQgSNko2WlXYnc2YjF7rihnbMkzjlq58FPJ77hTxXysoTZiJXDyg",
      "login_uri": "/api/v1/oauth/login",
      "state": "AruY3s6MMcMS4K4bn2T2zBqG8dW9vDxq_OX6zTUqA_yfveX_mF5TJ7KeSQgSNko2WlXYnc2YjF7rihnbMkzjlq58FPJ77hTxXysoTZiJXDyg",
      "expiry": "2022-09-16T14:44:27.256613564+07:00"
    }
  }
}

The key fields in the response are the authorize_url and the login_uri. The authorize_url must be opened in a browser window and allows the user to authorize with their provider and grant the necessary permissions to RPort so that it can obtain a provider access_token for checking the user and permitting access to access RPort. The login_uri is the RPort API endpoint that allows an OAuth authorization code to be to be used to login to RPort and obtain an RPort JWT Bearer token. The state value is the same as the state query param in the authorize_url and is provided for developer convenience. The expiry value indicates when the state value will expire, after which /auth/ext/settings must be called again to obtain a new authorize_url.

After the OAuth provider authorization has completed and after the user has been authenticated and they have granted RPort permission to access their details stored with the OAuth provider, then the OAuth provider server will redirect the browser back to the value configured via the redirect_uri configuration parameter (see Configuration Settings). Included as a query parameter in the redirect url will be an authorization code value and the state value (from the authorize_url). The authorization code can be used to login to RPort to obtain an RPort JWT Bearer token using the login_uri provided above. It is STRONGLY recommended that developers check that the value state value included matches the state value originally supplied in the authorize_url (see above). This will significantly reduce the chance of hackers potentially obtaining RPort access via OAuth CSRF (see OAuth 2.0 Threat Model and Security Considerations) attacks.

Logging in to RPort - Web App Style Flow

Once an authorization code has been obtained then it can be used to login to RPort and obtain an RPort JWT Bearer token using the login_uri included in the /auth/ext/settings response. An example is provided below:

export LOGIN_URI="/api/v1/oauth/login"
export CODEANDSTATE="code=6611e4160148e7babced&state=AruY3s6MMcMS4K4bn2T2zBqG8dW9vDxq_OX6zTUqA_yfveX_mF5TJ7KeSQgSNko2WlXYnc2YjF7rihnbMkzjlq58FPJ77hTxXysoTZiJXDyg"
curl -s "http://localhost:3000$LOGIN_URI/?$CODEANDSTATE" | jq

This will return a response similar to the below:

{
  "data": {
    "token": "eyJhbGcIOIJIUZI1NiIsInR5DCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IMRpcy1yb2JpbnMiLCJzY22WZXMiOlt7InVyaSI6IioiLCJtZXRobnQiOiIqIn0seyJ1cmkiOiIvYXBpL3YxL3AlcmlmeS0yZmEiLCJtZXRob2QiOiIqIiwiZXhjbHVkZSI6DHJ1ZX1dLCJqdGkiOiIxMZc4MzMwMjkwNjK1NjgzNzizNSJ9.p6VZ8S_OWltL9lgGWP27UK-Y612R9f_ZrlUPwOS3sDA",
    "two_fa": null
  }
}

The token field contains the RPort JWT Bearer token that can be used with subsequent RPort API calls.

User Sign-In - Device Style Flow

To initiate the user sign-in when running an CLI or similar constrained app, the /auth/ext/settings/device endpoint (as returned by the /auth/provider endpoint) must be called.

curl -s "http://localhost:3000/api/v1/auth/ext/settings/device" | jq

This will return a response similar to the below:

{
  "data": {
    "auth_provider": "microsoft",
    "details": {
      "login_uri": "/oauth/login/device",
      "auth_info": {
        "user_code": "AN9T6DQEF",
        "device_code": "SBQABAEEAAFD--DLA3Vf7QrddgJJ7Wevr_4FAnSQ6N2JKg9u2I2Qs9EZzbU9X7rnlmnsuwpT8ZwFM4YRVDZ4l9S_aE3DA-0jUAyQ7yEBE-hyMFcVaB9nfubMnkUgW-o5_ahaZ-XGGFeyRon0zOy_kJL_n0t7tp6EgwH-oIGB7vLU2nf7CVWdhn_XRGME_GhG532hXq9EmuV4gAA",
        "verification_uri": "https://microsoft.com/devicelogin",
        "expires_in": 900,
        "interval": 5,
        "message": "To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code SN9T8CSEF to authenticate."
      }
    }
  }
}

The auth_provider field repeats which OAuth provider is being used.

The login_uri is the rportd endpoint which should be polled to check if the user has authorized yet.

The verification_uri and user_code must be displayed to the signing in user who must then separately open a browser, visit the page indicated by the verification_uri and enter the user_code provided. After which they will be asked to authorize the RPort access. Once the user has authorized succesfully then calls to the login_uri will return an ok status.

The interval value indicates how long should be waited between authorization status checks via the login_uri.

The expires_in field indicates when the user_code provided will expire.

Logging in to RPort - Device Style Flow

To complete the sign-in, the URL previously returned as the login_uri must be polled to see if the user has completed their authorization yet. The call must include the device_code to identity the device (and therefore user) making the authorization request. The response will either be that the user has completed authorization, or that the authorization is still pending, or that there has been an error. Given a device_code, the login_uri can be checked as shown in the example below:

export DEVICE_CODE="e469c14g435103f8cd43bed2a633581f0be033b2"
curl -s "http://localhost:3000/api/v1/oauth/login/device?device_code=$DEVICE_CODE" | jq

On User Authorized

If the user has authorized, this will return a response similar to the below:

{
  "data": {
    "token": "eyJhbGcioiJIUzj1NiIqInR5cCc6IkpXwCJ9.eyJ1c3VybmFTZSI6Im3vcmVzdcF0aWMwMF9nbWFpBC5jb20jRVhUI0Btb3Jlc3RhdGlJMDBnbWFpbC5vbm1pY3Jvc30mdC5jb20iLCJzY29wZXMiOlt7InVyasi6IioiLCJtZXRob2QiOiIqIN0seyJ1cmkiOiIvYXBpL3YxL3ZlcmlmeS0yZmEiLCJtZXRob2QiOiIqIiwiZXhjbHVkZSI6dHJ1ZX1dLCJqdGkiOiIxMzY4MzM3NTYzODUyOTY5NTI3NSJ9.JKM4OZ_I5XgboJq9huityvkf5kJRibV4rIev0P-QWLs",
    "two_fa": null
  }
}

The token field contains the RPort JWT Bearer token that can be used with subsequent RPort API calls.

On User Authorization Pending (soft error)

If the user’s authorization is still pending then a response similar to the below will be returned:

{
  "data": {
    "status_code": 200,
    "error": "authorization_pending",
    "error_description": "The authorization request is still pending.",
    "error_uri": "https://docs.github.com/developers/apps/authorizing-oauth-apps#error-codes-for-the-device-flow"
  }
}

On Retry Too Soon (soft error)

If the user’s authorization status is checked before the interval period has completed then further requests will be rate limited and a slow_down response similar to the below will be returned:

{
  "data": {
    "status_code": 200,
    "error": "slow_down",
    "error_description": "Too many requests have been made in the same timeframe.",
    "error_uri": "https://docs.github.com"
  }
}

On Authorization Error (hard error)

If there’s an error then a response similar to the below will be returned:

{
  "data": {
    "status_code": 200,
    "error": "incorrect_device_code",
    "error_description": "The device_code provided is not valid.",
    "error_uri": "https://docs.github.com/developers/apps/authorizing-oauth-apps#error-codes-for-the-device-flow"
  }
}

Note that the OAuth providers are not consistent when returning http status codes. Therefore it is best to always check the value of error and when not empty handle the error accordingly. Only the authorization_pending and slow_down error are soft errors which can be retries. All other errors are hard and should be displayed to the user and the sign-in stopped.