How to get OTCS ticket using OAuth2 Client Credentials grant flow in OTDS

I have an unattended/automated task that uses the OTCS REST API to perform searches and add documents.

I would like to convert it to use the OAuth2 Client Credentials grant flow, so I can use a client secret rather than a username/password.

I have set up a new OAuth client in OTDS with default values, and have the client secret. I can use this info via powershell to gain an OAuth access_token using the /otdsws/oauth2/token API:

$headers = @{
    Authorization = "Bearer $accessToken"
}
$params = @{ requested_token_type="urn:ietf:params:oauth:token-type:access_token" grant_type="client_credentials" client_secret="(client secret here)" client_id="(client name here)" } Invoke-RestMethod "https://(otds url)/otdsws/oauth2/token" -Method 'POST' -Headers $headers -Body $params | Select -ExpandProperty access_token

 

This call is successful and I get the access token OK, however I need to convert this token into something I can use in the call to OTCS, as the OAuth access token is not usable as an OTDS/OTCS ticket:

$hdrs = @{
    "otcsticket"="$otcsticket"
}

Invoke-RestMethod "https://(otcs url)/otcs/cs.exe/api/v1/nodes/2000" -Headers $hdrs 

 

Any input appreciated, thanks,

Tagged:

Best Answer

  • markmarkmark
    markmarkmark Member
    #2 Answer ✓

    Leaving this here in case anyone has the same issue trying to use OAuth for unattended services working in OTCS…

    The key here was that I did not understand that it is possible to use "Bearer $token" as an authentication header when calling OTCS REST API (meaning no need for the old-style OTCS token), and that the $token could be an OAuth token retrieved from OTDS as I had already worked out how to do. The other part was that I needed to use the OAuth "Authorization Code" grant flow, not the "Client Credentials" grant flow.

    What I found incredibly frustrating was that there are no end-to-end worked examples with explanations that match my scenario - which doesn't seem like any kind of edge case, as surely I'm not the first person to ever try to automate interaction with OTCS via REST using OAuth?!

    What I have pieced together was from multiple forum posts (some going back to v10.5), what limited API docs exist (those that had useful comments rather than raw specifications), comms with colleagues and other experts, and a lot of trial and error.

    <#

    This example shows how to:
    - authenticate to OTCS using the OAuth Authorization Code grant flow
    - impersonate a user
    - download a document in OTCS to local disk as the user

    Note this example assumes all calls are successful.

    Pre-requisites in OTDS (note there may be other ways to achieve the same results):
    - Add auth client, allow client to impersonate, make confidential, set to named user partition (not global)
    - Use Access Role to grant user partition access to resource
    - Ensure specified user is in user partition

    Pre-requisites in OTCS
    - Grant user access to document

    #>

    $documentId = "153812" # Data ID of the document to download
    $documentDestination = "D:\test.pdf" # Local path where the document will be created

    $otcsUrl = "https://otcs" # OTCS base URL

    $otdsUrl = "https://otds" # OTDS base URL
    $clientid = "oauth-client" # OAuth client ID
    $clientSecret = "(some secret here)" # Client secret for $clientid
    $userId = "(some user id@domain)" # OTDS user ID of the account used to connect to OTCS



    # Ensure TLS 1.2 is used when calling Invoke-RestMethod
    Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12



    # 1. Call to OTDS to authenticate using the OAuth2 authorization code flow.
    # The token received will allow access to OTCS as the user in $userId
    #
    $authHeaders = @{
    accept = "application/json"
    }

    $authBody = @{
    requested_token_type = "urn:ietf:params:oauth:token-type:access_token"
    grant_type = "urn:ietf:params:oauth:grant-type:token-exchange"
    client_id = $clientId
    client_secret = $clientSecret
    subject_token = $userId
    subject_token_type = "urn:opentext.com:oauth:string:user_id"
    }

    $oauthToken = Invoke-RestMethod "$otdsUrl/otdsws/oauth2/token" -Method 'POST' -Headers $authHeaders -Body $authBody | Select -ExpandProperty access_token



    # 2. Call to OTCS to download the document of interest as user $userId
    # using the OAuth bearer token.
    #
    $downloadHeaders = @{
    Authorization = "Bearer $oauthToken"
    }

    $documentUrl = "$otcsUrl/otcs/llisapi.dll/api/v2/nodes/$documentId/content"

    Invoke-RestMethod $documentUrl -Method Get -Headers $downloadHeaders -OutFile $documentDestination

Answers

  • markmarkmark
    markmarkmark Member
    #3 Answer ✓

    Leaving this here in case anyone has the same issue trying to use OAuth for unattended services working in OTCS…

    The key here was that I did not understand that it is possible to use "Bearer $token" as an authentication header when calling OTCS REST API (meaning no need for the old-style OTCS token), and that the $token could be an OAuth token retrieved from OTDS as I had already worked out how to do. The other part was that I needed to use the OAuth "Authorization Code" grant flow, not the "Client Credentials" grant flow.

    What I found incredibly frustrating was that there are no end-to-end worked examples with explanations that match my scenario - which doesn't seem like any kind of edge case, as surely I'm not the first person to ever try to automate interaction with OTCS via REST using OAuth?!

    What I have pieced together was from multiple forum posts (some going back to v10.5), what limited API docs exist (those that had useful comments rather than raw specifications), comms with colleagues and other experts, and a lot of trial and error.

    <#

    This example shows how to:
    - authenticate to OTCS using the OAuth Authorization Code grant flow
    - impersonate a user
    - download a document in OTCS to local disk as the user

    Note this example assumes all calls are successful.

    Pre-requisites in OTDS (note there may be other ways to achieve the same results):
    - Add auth client, allow client to impersonate, make confidential, set to named user partition (not global)
    - Use Access Role to grant user partition access to resource
    - Ensure specified user is in user partition

    Pre-requisites in OTCS
    - Grant user access to document

    #>

    $documentId = "153812" # Data ID of the document to download
    $documentDestination = "D:\test.pdf" # Local path where the document will be created

    $otcsUrl = "https://otcs" # OTCS base URL

    $otdsUrl = "https://otds" # OTDS base URL
    $clientid = "oauth-client" # OAuth client ID
    $clientSecret = "(some secret here)" # Client secret for $clientid
    $userId = "(some user id@domain)" # OTDS user ID of the account used to connect to OTCS



    # Ensure TLS 1.2 is used when calling Invoke-RestMethod
    Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12



    # 1. Call to OTDS to authenticate using the OAuth2 authorization code flow.
    # The token received will allow access to OTCS as the user in $userId
    #
    $authHeaders = @{
    accept = "application/json"
    }

    $authBody = @{
    requested_token_type = "urn:ietf:params:oauth:token-type:access_token"
    grant_type = "urn:ietf:params:oauth:grant-type:token-exchange"
    client_id = $clientId
    client_secret = $clientSecret
    subject_token = $userId
    subject_token_type = "urn:opentext.com:oauth:string:user_id"
    }

    $oauthToken = Invoke-RestMethod "$otdsUrl/otdsws/oauth2/token" -Method 'POST' -Headers $authHeaders -Body $authBody | Select -ExpandProperty access_token



    # 2. Call to OTCS to download the document of interest as user $userId
    # using the OAuth bearer token.
    #
    $downloadHeaders = @{
    Authorization = "Bearer $oauthToken"
    }

    $documentUrl = "$otcsUrl/otcs/llisapi.dll/api/v2/nodes/$documentId/content"

    Invoke-RestMethod $documentUrl -Method Get -Headers $downloadHeaders -OutFile $documentDestination