A token request is rejected with a 40144 error when an authorization header is present in auth_headers
Steps to reproduce:
- Setup an endpoint to use as an
auth_urland have the auth_url require authentication. Return aTokenRequestvia the endpoint withauth.create_token_request - Setup an AblyRealtime instance to use
auth_urlandauth_headersin its client options
Expected Result:
The authorization header is used to authenticate the client to the auth_url and the subsequent request from the client to get a token from the request token endpoint is successful.
As per the spec item TO3j8 and Ably docs the headers should be used in requests to the auth_url which implies that they shouldn't be sent in the token request to Ably.
Including an authorization header in authHeaders in ably-js for this scenario works
Actual result:
The request is rejected by realtime and the client goes to the disconnected state
ConnectionManager.on_error_from_authorize(): err = 40144 401 Unexpected error decoding Ably token or JWT; the token is not valid
ConnectionManager.on_error_from_authorize: Client configured authentication provider request failed
ConnectionManager.notify_state(): new state: ConnectionState.DISCONNECTED
Workarounds:
- Return a JWT or Ably token to the client which wont require a request to the request token endpoint
- Use
auth_callbackinstead ofauth_url
Thanks for raising @mclark-ably. A couple of questions:
- do we know whether this is affecting any customers?
- were you able to confirm how the library treats the
Authorizationheader that's provided inauth_headers; does it simply not send anAuthorizationheader or does it replace it with something else?
Hi @lawrence-forooghian
- This was raised by a customer and after doing a bit of testing I was able to replicate the same. They are using auth_callback now to work around the issue so is not currently a blocking issue for them.
- It appears the
Authorizationheader which is used to authenticate the client to the configured auth_url is also used when the client does a post to the request an ably token
This line in request_token gets the auth_headers and uses those headers in the post to the ably requestToken endpoint which I think is where the issue lies as the authorization header is used on the realtime side to try and authenticate the request
Hey @mclark-ably, could you please share the code snippet for both the server.py and client.py files? It would also be really helpful if you could add comments at the relevant sections. Thanks!
You can try the same from the following code:
from flask import Flask,jsonify, make_response, request
import json
from ably import AblyRest
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
client = AblyRest(key = "<ably_API_key>")
@app.route('/')
async def index():
token_details = await client.auth.create_token_request(
{
"capability": {
"*": ["subscribe", "presence"]
},
}
)
response = make_response(token_details.to_dict())
return jsonify(token_details.to_dict())
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
and client(using any random JWT)
headers = {
"Authorization": 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
}
async def main():
client = AblyRealtime(
auth_url="<auth_url>",
auth_headers=headers,
)
As said it appears the header to authenticate to the auth server is also send to the requestToken endpoint