opendatadiscovery / odd-platform

First open-source data discovery and observability platform. We make a life for data practitioners easy so you can focus on your business.
https://opendatadiscovery.org
Apache License 2.0
1.19k stars 98 forks source link

Calling API's endpoint for ODD Platform which is behind SSO #1639

Closed mavenzer closed 5 months ago

mavenzer commented 6 months ago

I have deployed the Open Data Discovery Platform in a Kubernetes cluster and integrated MobileSSO for user authentication. I am encountering issues with specific authentication flows:

Flow 1: Machine-to-Machine (M2M) Authentication For the M2M flow, where external systems need to call ODD APIs, we generate an access token from our AUTH server and pass this token as a Bearer token in the API call. However, it seems the API does not verify the token as expected. I'm not sure how to add the CLIENT_ID and SCOPES for the M2M flow in the deployment config as the CLIENT_ID/Scope are different for U2M vs M2M flows(Since our auth server have M2M flow defined)


import requests

# OAuth Token Endpoint Configuration
token_url = "https://ssobroker.backbone.net:443/as/token.oauth2"
client_id = "CLI_MYACCESS_M2M_FLOW"
scope = "SCO_MYACCESS_ODD"  

client_cert_path = r'\\CLI_MYACCESS_M2M_FLOW.test.pem' 
client_key_path =   r'\\SCO_MYACCESS_ODD.test.key'
ca_certs= r'\\custom-ca-certs.ca'
api_base_url = "https://odd-platform-testingconfig-alex.com"  
api_endpoint = "/api/namespaces?page=1&size=1"

def get_access_token():
    payload = {
        "grant_type": "client_credentials",
        "client_id": client_id,
        "scope": scope
    }
    response = requests.post(token_url, data=payload, cert=(client_cert_path, client_key_path))

    if response.status_code == 200:
        return response.json().get('access_token')
    else:
        print("Failed to obtain access token:", response.status_code, response.text)
        return None

# Function to call the application API with the access token
def call_api(access_token):
    headers = {
        "Authorization": f"Bearer {access_token}",
        "accept": "application/json",
    }

    response = requests.get(api_base_url + api_endpoint, headers=headers,verify=ca_certs)

    if response.status_code == 200:
        return response.text
    else:
        print("Failed to call API:", response.status_code, response.text)
        return None

access_token = get_access_token()
print(access_token)
if access_token:
    api_response = call_api(access_token)
    if api_response:
        print("API response:", api_response)

I am redirected to an SSO login page (https://ssobackbone.onelogin.com/login) instead of being call the API endpoint.

The OIDC config which I have defined in the ODD_PLATFORM(0.23.2)

            - name : AUTH_TYPE
              value: "OAUTH2"
            - name : AUTH_OAUTH2_CLIENT_MOBILESSO_PROVIDER
              value:  "mobilesso"
            - name: AUTH_OAUTH2_CLIENT_MOBILESSO_CLIENT_ID
              value: "CLIENT_ID_TESTING_ODD"
            - name: AUTH_OAUTH2_CLIENT_MOBILESSO_PKCE
               value:  "true"    
            - name: AUTH_OAUTH2_CLIENT_MOBILESSO_CHALLENGE_METHOD
              value: "S256"
            - name: AUTH_OAUTH2_CLIENT_MOBILESSO_SCOPE
              value: "openid"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_REDIRECT_URI
              value: "https://odd-platform-testingconfig-alex.com/login/oauth2/code/CLIENT_ID_TESTING_ODD"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_CLIENT_NAME
              value:  "MobileSSO"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_ISSUER_URI
              value:  "https://generic-v1-test-kalix.com/FedBroker"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_USER_NAME_ATTRIBUTE
              value:  "email"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_ADMIN_ATTRIBUTE
              value: "email"
            - name:  AUTH_OAUTH2_CLIENT_MOBILESSO_ADMIN_PRINCIPALS
              value: "rnn@kaslix-test.com"

Do we need to add the M2M client_ID and scopes in the deployment yaml?

Almost the identical thing is happening when I'm trying to call the endpoints in Postman(https://odd-platform-testingconfig-alex.com/api/namespaces?page=1&size=1`). I have used the Oauth2 as AUTH type with all the above details in the deployment config. It being redirected to the.I am redirected to an SSO login page (https://ssobackbone.onelogin.com/login) instead of being call the API endpoint.

Am i'm missing something in the deployment config or the Python code for calling the M2M flows ? Best Regards,

Vladysl commented 6 months ago

Hi @mavenzer Thank you for you feedback. If I understand you correct, you try to create some long-term token which can be used for auth in the ODD platform. We don't support this. In case you want to make some Postman/M2M request you should use SESSION Cookie. you will receive it after successful auth.

image

and than you can use this SESSION in your requests

image

We will try to add long-term token support in future releases. If you have any questions, feel free to ask them here.

mavenzer commented 6 months ago

Hi @Vladysl Thanks for the update, It would be much better/standard practice if there is some kind of Long term token that can be used for auth in the ODD's API.

I still could not use the Session as you mentioned to pass in the headers for the M2M flows. can you elaborate the process as the CLIENT_ID/scopes for the M2M is different for our case what we used for the U2M flows?

mavenzer commented 6 months ago

Hi @Vladysl We are cannot use SESSION as it's being restricted by policy due to security. It would be much better if we can create long-term token in ODD platform for the authentication.

Vladysl commented 5 months ago

Hi @mavenzer , Could you please let us know how urgently you need this?  We can add an additional environment variable that should store some long-term generated token, and you should use this token in the header to perform API requests. 

mavenzer commented 5 months ago

Thanks @Vladysl for the response, I really appreciate it. So we are in the last stages of integrating ODD to our platform and calling API endpoints with some long term token is absolutely critical for triggering the downstream automation flows. Can you please elaborate on the type of ENVIRONMENT variable that can be used as headers in api request? Does the variable comes from AUTH server or we can store it in ODD platform itself?

Vladysl commented 5 months ago

Right now, probably we will make a fast solution with variable like(this is a draft; more details will be in implementation):

auth.type = token
auth.token = <some_token>

And you should use in your requests to the ODD platform. On our end, we will simply compare the token from the request with the token from auth.token  @mavenzer

mavenzer commented 5 months ago

@Vladysl just asking few silly questions :
Does that mean defining the AUTH token in the deployment config itself ?
What will be the validity for these kinds and tokens and how to renew/generate a new one? Correct me if I'm wrong this token will act as proxy for authorization of the resources in ODD ?

Vladysl commented 5 months ago

@mavenzer

1.Yes, you need to define it in the deployment config 2.It will depend on our realisation. We will provide token example and where you can generate it.(on case you want to renew token, you should redeploy or application)

  1. We will simply validate whether the user token is valid and perform a request or throw a 401 unauthorised.
mavenzer commented 5 months ago

@Vladysl Sounds perfect to me! One more question, can we pass a bearer token from the AUTH server to validate our identity ? (just curios to know!)

Vladysl commented 5 months ago

@mavenzer if you put it in deployment config, then yes, you can

mavenzer commented 5 months ago

Okay got it, but most of the Bearer token coming from AUTH server will have some validity max (30 mins to 1hrs ). It would be better if we can generate the token in ODD platform and put it the deployment Config to validate the identity of the users.

@Vladysl

Vladysl commented 5 months ago

Hi @mavenzer, We created minor release - v0.24.1 We added 2 env variables

auth.s2s.enabled - true/false
auth.s2s.token - <any_string>

In case, you want to perform S2S or M2M request, you need to pass

auth.s2s.enabled: true 
auth.s2s.token : stringExample

and for each request provide Header 'X-API-Key: stringExample'

mavenzer commented 5 months ago

I am truly grateful for your assistance@Vladysl . It really solved the issues for last mile automation. Really appreciate your efforts.