Authenticate user from severless app

We have an S3 bucket full of files (documentation etc. specific to each product) but the customer can only download the files if they have signed an NDA.

We would like to add a link to the files in our Freshdesk wiki (say helpdesk.foo.com)

When the user presses the files, they are sent to another domain (say downloads.foo.com)

When the severless platform sees the request to downloads.foo.com, it wants to make sure the Freshdesk user has permission (company signed NDA - custom company property, something like this) before forwarding the file data from the S3 bucket, otherwise just show an error.

My question is this - how can the other web page on another domain login the current user with Freshdesk so that it can download their company data to know whether they signed the NDA?

Is the “external app” mentioned on this page (Freshworks Developer Docs | Implement OAuth authorization flow in external apps (that access Freshworks resources)) the correct use-case for calling from a severless app?

In this case the serverless app would redirect the user to the oauth page using headers and the Freshdesk login page would redirect them back to the file?

Something like this (ChatGPT used):

Detailed Implementation Steps

1. User Authorization

Redirect Users for Authorization:

Construct the URL to redirect users to Freshdesk’s authorization endpoint:

python

Copy code

from urllib.parse import urlencode

def get_authorization_url(client_id, redirect_uri):
    base_url = 'https://yourdomain.freshdesk.com/oauth/authorize'
    params = {
        'response_type': 'code',
        'client_id': client_id,
        'redirect_uri': redirect_uri,
        'scope': 'read'
    }
    return f"{base_url}?{urlencode(params)}"

Example URL:

bash

Copy code

https://yourdomain.freshdesk.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=read

2. Exchange Authorization Code for Access Token

Handle Callback and Exchange Code:

When Freshdesk redirects back to your application with an authorization code, exchange it for an access token:

python

Copy code

import requests

def get_access_token(auth_code, client_id, client_secret, redirect_uri):
    token_url = 'https://yourdomain.freshdesk.com/oauth/token'
    data = {
        'grant_type': 'authorization_code',
        'code': auth_code,
        'redirect_uri': redirect_uri,
        'client_id': client_id,
        'client_secret': client_secret
    }
    response = requests.post(token_url, data=data)
    return response.json().get('access_token')

3. Verify NDA Status and Serve File

Backend Service to Check NDA and Serve Files:

Implement a backend service that checks the NDA status and serves the file:

python

Copy code

import json
import boto3
import requests
from flask import Flask, request, redirect, jsonify

app = Flask(__name__)
s3_client = boto3.client('s3')
freshdesk_domain = 'yourdomain.freshdesk.com'
client_id = 'YOUR_CLIENT_ID'
client_secret = 'YOUR_CLIENT_SECRET'
redirect_uri = 'YOUR_REDIRECT_URI'

def check_nda_status(access_token, user_id):
    headers = {'Authorization': f'Bearer {access_token}'}
    response = requests.get(
        f'https://{freshdesk_domain}/api/v2/users/{user_id}',
        headers=headers
    )
    user_data = response.json()
    return user_data.get('custom_fields', {}).get('nda_signed', False)

def generate_presigned_url(bucket_name, object_key):
    response = s3_client.generate_presigned_url(
        'get_object',
        Params={'Bucket': bucket_name, 'Key': object_key},
        ExpiresIn=3600
    )
    return response

@app.route('/download', methods=['GET'])
def download_file():
    auth_code = request.args.get('code')
    file_key = request.args.get('file_key')

    if not auth_code or not file_key:
        return jsonify({'error': 'Missing parameters'}), 400

    # Exchange authorization code for access token
    access_token = get_access_token(auth_code, client_id, client_secret, redirect_uri)
    
    # Use the access token to get user information
    user_info_response = requests.get(
        f'https://{freshdesk_domain}/api/v2/users/me',
        headers={'Authorization': f'Bearer {access_token}'}
    )
    user_info = user_info_response.json()
    user_id = user_info.get('id')
    
    # Check NDA status
    nda_signed = check_nda_status(access_token, user_id)

    if nda_signed:
        # Generate presigned URL for S3
        url = generate_presigned_url('your-bucket', file_key)
        return redirect(url)
    else:
        return jsonify({'error': 'Access denied. NDA not signed.'}), 403

if __name__ == '__main__':
    app.run()

I have tried step 1 using URL like this:

https://MYSUBDOMAIN.myfreshworks.com/org/oauth/v2/authorize?response_type=code&client_id=REALCLIENTID&state=1234567890&scope=freshservice.solutions.view&redirect_uri=https://localhost:10001/auth/callback

Except MYSUBDOMAIN and REALCLIENTID are real values.

I get the proper flow to pick:

But when I select Freshdesk and press next, then I get this error even though my account is Super Admin: