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:
- Sign up and create an Okta Account
- Create the Okta Developer App Registration
- Create User Groups
- Create and Assign Users to the Okta App
- Create a Group Claim
- Verify Okta Authorization configuration
- Configure OAuth Settings in the Transform Distribution Server
- Develop and Deploy the Transform code
- Configure Seed and pair with Transform
- 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 type" setting 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
Setting | Value |
Authenticator Name | Okta Open ID OAuth |
Description | Okta Open ID OAuth Config |
Version | OAuth 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 Name | maltego.web.api.key.okta |
Access Token Variable Description | Okta 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.