question

vban2001 avatar image
vban2001 asked dsafonov answered

No Refresh Token given during oauth 2.0 flow and it is driving me insane.

Hello I currently have a rest API that serves as our oauth service. Right now I am able to complete the flow initially when the user authorizes the app to their merchant. But now comes the need for refreshing access tokens.

According to: https://docs.clover.com/docs/refresh-access-tokens
You can make a POST to /oauth/v2/refresh with your client id and refresh token as parameters. But the thing is it is not clear whatsoever at all how you are supposed to get this refresh token. Trying the no_refresh_token route returns a authentication error. After a literal month of debugging I have come no closer to being able to refresh our tokens and it has seriously road blocked our app development.

My current rest API:

import http.client
import json

# load config file
from bottle import get, request, run

file = open('config.json')
data = json.load(file)
file.close()

# load id and secret
app_id: str = data["app_id"]
app_secret: str = data["app_secret"]


class Credentials:
    def __init__(self):
        self.token = None
        self.mid = None

credentials = Credentials()


# set up server endpoints
@get('/')
def authorize() -> str:
    return '''<a href="https://sandbox.dev.clover.com/oauth/authorize?client_id={0}">Click here</a>
            to authorize the application.'''.format(app_id)


@get('/callback')
def callback() -> str:
    auth_code: str = request.query.get('code')
    mid: str = request.query.get('merchant_id')

    print(request)

    print(f'Received auth code: {
                  auth_code}\n'
          f'Received MID: {
                  mid}')

    if mid:
        credentials.mid = mid

    # if we have an auth code make a request for token
    if auth_code:
        request_body = {
            'client_id': app_id,
            'client_secret': app_secret,
            'code': auth_code
        }

        connection = http.client.HTTPSConnection('sandbox.dev.clover.com')

        # for http requests to clover
        oauth_request_headers = {
                 'Authorization': 'Client ' + app_id,
                                 'Accept': 'application/json',
                                 'Content-Type': 'application/json'}

        connection.request('POST', '/oauth/token', json.dumps(request_body), oauth_request_headers)

        # parse out returned data
        response_body = json.loads(connection.getresponse().read())

        print('Response Body: ')
        print(response_body)

        if response_body['access_token']:
            credentials.token = response_body['access_token']
            return 'Authorization succeeded, app now has a token ready for connector'

        else:
            return 'Authorization failed: No Access Token received'

    else:
        return authorize()


@get('/get_token')
def get_token() -> str:
    if credentials.token and credentials.mid:
        data = {
            "token": credentials.token,
            "mid": credentials.mid
        }

        return json.dumps(data, indent=4)
    else:
        return "No API_TOKEN Given Yet!, please authorize the app."


run(host='localhost', port=8090)


with our flowing going

authorize -auth_code, mid -> callback -> get_token -> token


I very much need support with this since I have exhausted all of my options.

OAuthAPI Tokenaccess token
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jcy avatar image
jcy answered jcy edited
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

vban2001 avatar image
vban2001 answered

@ getting this error now and I am unsure as to why.

Response Body:

{'status': 'Unauthorized', 'message': 'Failed to validate authentication code.'}

10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

dsafonov avatar image
dsafonov answered

To get this to work in sandbox you need to send the user to /oauth/v2/authorize instead of /oauth/authorize. Then, this will work in sandbox.

However in prod, still see "Failed to validate authentication code." from /oauth/v2/token even when sending users to /oauth/v2/authorize. Very frustrating.

10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

vban2001 avatar image
vban2001 answered

I tired that already. There must be something else wrong then.

10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

jcy avatar image
jcy answered
import http.client
import json

# load config file
from bottle import get, request, run

file = open('config.json')
data = json.load(file)
file.close()

# load id and secret
app_id: str = data["app_id"]
app_secret: str = data["app_secret"]

class Credentials:
    def __init__(self):
        self.token = None
        self.mid = None
credentials = Credentials()

# set up server endpoints
@get('/')
def authorize() -> str:
    return '''<a href="https://sandbox.dev.clover.com/oauth/v2/authorize?client_id={0}">Click here</a>
            to authorize the application.'''.format(app_id)

@get('/callback')
def callback() -> str:
    auth_code: str = request.query.get('code')
    mid: str = request.query.get('merchant_id')

    print(request)

    print(f'Received auth code: {auth_code}\n'
          f'Received MID: {mid}')

    if mid:
        credentials.mid = mid

    # if we have an auth code make a request for token
    if auth_code:
        request_body = {
            'client_id': app_id,
            'client_secret': app_secret,
            'code': auth_code
        }

        connection = http.client.HTTPSConnection('apisandbox.dev.clover.com')

        # for http requests to clover
        oauth_request_headers = {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        }

        connection.request('POST', '/oauth/v2/token', json.dumps(request_body), oauth_request_headers)

        # parse out returned data
        response_body = json.loads(connection.getresponse().read())

        print('Response Body: ')
        print(response_body)

        if 'access_token' in response_body:
            credentials.token = response_body['access_token']
            return 'Authorization succeeded, app now has a token ready for connector'
        else:
            return 'Authorization failed: No Access Token received'
    else:
        return authorize()

@get('/get_token')
def get_token() -> str:
    if credentials.token and credentials.mid:
        data = {
            "token": credentials.token,
            "mid": credentials.mid
        }

        return json.dumps(data, indent=4)
    else:
        return "No API_TOKEN Given Yet!, please authorize the app."

run(host='localhost', port=8090)
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

vban2001 avatar image
vban2001 answered
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

dsafonov avatar image
dsafonov answered
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Welcome to the
Clover Developer Community