OAuth Example Two - Okta OpenID Connect Integration

Modified on: Thu, 3 Aug, 2023 at 11:18 PM

Overview

This use case describes how user authorization can be achieved through OAuth 2.0 via scoped access tokens, as well as user authentication via OPENID Connect. To achieve this, we will be integrating Maltego with the Okta OpenID Connect & OAuth 2.0 API


Use Case

We will configure an Identity Management Application (iDM) on Okta which will be responsible for authenticating users through OPENID Connect and OAuth. We will integrate this IDP application with Maltego and demonstrate how identity management can be done through OAuth in the Maltego ecosystem.


Finally, we will create a Transform that will require initial sign-in on our iDM provider website [Okta] and will return varying information depending on the user access rights.  There will be two user groups, free and paid users.


After creating an Okta developer application, we will add users and provide them with varying permissions. Configure OAuth on the apps to allow the Maltego client to redirect users to the Okta website to login, Okta will return a token to Maltego which can then be used by the Transform to make queries. 


We will then show how developers can create Transforms which use the retrieved access token to verify the access rights allocated to a user.


This tutorial is broken into the following parts:

  1. Sign up and create an Okta Account
  2. Create the Okta Developer App Registration
  3. Create User Groups
  4. Create and Assign Users to the Okta App
  5. Create a Group Claim
  6. Verify Okta Authorization configuration
  7. Configure OAuth Settings in the Transform Distribution Server
  8. Develop and Deploy the Transform code
  9. Configure Seed and pair with Transform
  10. Run and Test Transform


Tutorial


1. Signup for an Okta account via https://developer.okta.com/signup/ 

2. Login and create an application

 


In the Create New Application window, select Web and click Next



In the Application Settings section, input the OAuth settings. We will be using the following

Callback URLs:


https://127.0.0.1:63141/callback    

http://127.0.0.1:63141/callback


Allowed OAuth Grant Types: Authorization Code



Take note of you Client ID and Client Secret.


3. . Create User Groups

3.1 Create two groups free and paid



4. Create Users and add to Groups

4.1 Add a user and assign to the free group



4.2 Add another user and add to the paid group



5. Create a custom token claim


Tokens contain claims which are statements about the subject or another subject, for example; name, role, email address or the groups that they belong to. We will need to add a claim to include the user group information in the access token. E.g.

 

  "scp": [
"openid"
],
"sub": "test.maltego@outlook.com",
"groups": [
"Everyone",
"free"
]


Navigate to API -> Authorization Servers -> Default

 


5.1 Add Claim for ID Token


Add a new Claim named "groups"This claim will have a value type groups and we will use a wildcard regex, this means if the groups claim is set for an authorization server it will return all the user groups the person belongs to. We also set that this claim will only be available when the openid scope is requested. As shown in the image below:

 

5.2 Add Claim for Access Token


Repeat the process, but for the include in token typesetting choose Access Token



6. Verify configuration


Okta provides a token preview which simulates how the token will look like when a user authenticates correctly. Confirm that the group is shown in the token JSON as shown below.

 


7. Configure OAuth Settings in the Transform Distribution Server

7.1 Open your iTDS server or to the public TDS and create an account. Open OAuth Settings

7.1.1 Public TDS OAuth Settings Image

7.1.2 Internal TDS OAuth Settings Image



7.1.3 Settings Configuration


 

SettingValue
Authenticator NameOkta Open ID OAuth
DescriptionOkta Open ID OAuth Config
VersionOAuth 2.0
Access Token Endpoint https://dev-617245.okta.com/oauth2/default/v1/token?grant_type=authorization_code
Request Token Endpoint https://dev-617245.okta.com/oauth2/default/v1/authorize?client_id={apiKey}&response_type=code&scope=openid&redirect_uri={callback}&state=randomstate
Authorization URL https://dev-617245.okta.com/oauth2/default/v1/authorize?client_id={apiKey}&response_type=code&scope=openid&redirect_uri={callback}&state=randomstate
Application Key
This is the Application ID from the step 2.9

Application Secret
This is the Application ID from the step 2.9

Icon
Please note to use a very small resolution image. The Maltego client does not accept very large b64 images. Use 64X64 or less

For base64 icon, download an icon for a provider and resize it to 64x64 using https://appiconmaker.co or https://www.websiteplanet.com/webtools/favicon-generator/ and encode it using https://www.base64-image.de/
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

Access Token Variable Namemaltego.web.api.key.okta
Access Token Variable DescriptionOkta OAuth Token
Public Key
For the key pair, you can generate your own pair or use the one provided by Maltego and copy it a secure place. We do have access to your Private Key




Private Key


8. Develop and Deploy the Transform code


We will be using the Maltego open source maltego-trx library to develop the demo Transform. Upon completion this will need to be deployed to a publicly accessible server such as a VPS or VM.  You need to have Python3 and pip installed.


8.1 Install the Prerequisite Software


python3 -m pip install --user virtualenv
python3 -m venv oauth-venv
(oauth-venv) pip install maltego-trx
// install version 1.3.7+ only


8.2 Create a maltego-trx project


(oauth-venv) maltego-trx start okta_openid_project

This will create a folder okta_openid_project with the example project



8.3 Adding a Transform


Add a new Transform by creating a new python file titled OktaOpenID.py in the "transforms" folder. 

Any Python file in the transforms folder whose class name matches the filename and the class inherits from Transform, will automatically be discovered, and added to your Transform server.


Add the following files and the corresponding code.


8.4 Create File: okta_openid_project /transforms/OktaOpenID.py


import base64
from pathlib import Path

import requests
from maltego_trx.entities import Phrase
from maltego_trx.maltego import UIM_TYPES
from maltego_trx.oauth import MaltegoOauth
from maltego_trx.transform import DiscoverableTransform


class OktaOpenID(DiscoverableTransform):
    """
    Decrypts Okta Access Token and check if it is valid and verifies if a user belongs to free or paid groups
    """

    @classmethod
    def create_entities(cls, request, response):
        # variables for making a POST verification api call to OKTA
        introspect_url = "https://dev-<name>.okta.com/oauth2/default/v1/introspect?token="
        client_id = "<ID>"
        client_secret = "<SECRET>"
        payload = {}
        headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        b64_auth_bytes = base64.b64encode(
            (client_id + ":" + client_secret).encode("utf-8"))
        b64_encoded_auth = str(b64_auth_bytes, "utf-8")

        try:
            # get the encrypted token from the client, this is the Access Token Variable Name set in the iTDS
            encrypted_secrets = request.getTransformSetting(
                'maltego.web.api.key.okta')
            private_key_path = Path("private_key.pem").resolve()
            token_fields = MaltegoOauth.decrypt_secrets(private_key_path,
                                                        encrypted_secrets)
            token = token_fields['token']
            token_verification_url = introspect_url + token + "&token_type_hint=access_token"
            headers['Authorization'] = 'Basic ' + b64_encoded_auth
            result = requests.request("POST", token_verification_url,
                                      headers=headers,
                                      data=payload)
            """ The following output is how the response from Okta looks like
                 {
                        "active": true,
                        "scope": "openid",
                        "username": "example@maltego.com",
                        "exp": 1596735524,
                        "iat": 1596731924,
                        "sub": "tm@maltego.com",
                        "aud": "api://default",
                        "iss": "https://dev-<name>.okta.com/oauth2/default",
                        "jti": "JWT",
                        "token_type": "Bearer",
                        "client_id": "ID",
                        "uid": "UID",
                        "groups": [
                            "Everyone",
                            "paid"
                        ]
                    }
                """
            active = result.json()['active']
            if (active):
                cls.checkUserType(result.json(), response)
            else:
                response.addUIMessage("Token Expired please login again",
                                      UIM_TYPES["partial"])
        except Exception as e:
            response.addUIMessage("Error" + str(e),
                                  UIM_TYPES["partial"])

    @classmethod
    def checkUserType(cls, token_payload, response):
        groups = token_payload['groups']
        print(groups)
        if "paid" in groups:
            text = "free user: " + str(token_payload)
            paid_response = response.addEntity(Phrase, text)
        elif "free" in groups:
            text = "free user: " + str(token_payload)
            free_response = response.addEntity(Phrase, text)
        else:
            text = "unknown user group"
            unknown_response = response.addEntity(Phrase, text)
8.5 Add the private key from step 7.1.3 for decryption 

8.5.1 Create file : okta_openid_project /private key.pem

    Add the contents of the private key to this PEM file. It is possible to just upload/save the actual PEM file to this location if

    you have it as a PEM file.


8.6 Navigate to okta_openid_project /

8.7 Run the maltego-trx project with:

 

(oauth-venv)python project.py runserver

If all went well, you should see something like this:

 


8.8 Deploy the entire project folder / okta_openid_project to a remote VPS/VM/Dockerized environment. 

More details on how to deploy for production can be found here for standard web deployment and here for Docker containerized deployment. The simplest method for this tutorial is to upload the folder to a remote server through git or ftp.


8.9 Navigating to your VPS IP http://<ip-address>/run/oktaopenid in a browser you should the following output. If it doesn’t not work check that you have opened the necessary, port on the firewall.



9. Configure Seed and pair with Transform


Now that we have our Transform up and running, we need to create a Seed to distribute the Transform. The TDS will generate a random alphanumeric Seed name for you, but you can also use one of your choosing.



10.1 Add Transform and OAuth Settings to Seed.

Next, we need to add the Transform, we also add the OAuth setting and the Input Entity and Seed.

 


10.2 Install Seed in the Maltego Client

After we have added the Transform, we can now install our Seed in Maltego.



10.3 Verify the OAuth Settings in the Service Manager

We can view the OAuth Authenticator settings in the Service Manager by selecting the Manage Services options in the Transforms menu. Cross-check that the protocol set in step 2.3 is the same as those shown here. The settings the Service Manager correspond should correspond to the callback URL set in the provider Application.



10.4 Run the Transform

Drag a Phrase Entity onto an empty graph, right click and run the Transform.


 

 


Upon running the Transform, a prompt will appear asking you to sign in to use the Transform. Click Sign In. A browser page will be opened with the URL http://127.0.0.1:63141/signin. We are redirected to the Okta login page, please note you might observe a warning sign in the browser, ignore it and proceed.


 

The application we created will accept logins from the users registered with Okta and added to the application we created earlier. In an organizational setup the privileges will be set by the admin.



Following successful login, a user can now make a query and the Transform will check if they are allowed to run the Transform. Our example Transform checks the group a user belongs to. E.g. when a user in the free group logs in, they would only receive the details applicable to free users.


 

When the token expires, a warning message will appear informing the user that they are required to sign in again.




Note: To shorten authorization urls and to reference the returned token, Maltego uses configuration placeholders as follows:

For OAuth 2, "apiKey" and "callback" can be used as replacement variables in the authorization URL, e.g. http://example.com/oauth2/authorize?client_id={apiKey}&redirect_uri={callback}.

For OAuth 1.0a, only "token" can be used as a replacement variable, e.g. http://example.com/oauth1/authorize?oauth_token={token}.

For further explanation regarding OAuth endpoint configuration, please read more here.

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.