Authentication Related Code Samples#
Warning
Access Tokens, Refresh Tokens and Client Secrets are generally considered secret and should not live in your code. We print them here so that these examples are useful but you should generally not expose any of these tokens to systems or clients you don’t trust.
Get a JWT with a Username and Password#
import requests
from pprint import pprint
token_request = requests.post(
f"http://lms.example.com/oauth2/access_token",
data={
"client_id": "login-service-client-id",
"grant_type": "password",
"username": "test_user",
"password": "test_password",
"token_type": "JWT",
},
)
pprint(token_request.json())
{'access_token': 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiAibG1zLWtleSIsICJleHAiOiAxNjkyMjExNjM4LCAiZ3JhbnRfdHlwZSI6ICJwYXNzd29yZCIsICJpYXQiOiAxNjkyMjA4MDM4LCAiaXNzIjogImh0dHA6Ly9sb2NhbGhvc3Q6MTgwMDAvb2F1dGgyIiwgInByZWZlcnJlZF91c2VybmFtZSI6ICJmZWFuaWwiLCAic2NvcGVzIjogWyJyZWFkIiwgIndyaXRlIiwgImVtYWlsIiwgInByb2ZpbGUiXSwgInZlcnNpb24iOiAiMS4yLjAiLCAic3ViIjogIjVjMTBmNjZmMmQ2MzkwYjcwNjYyYzkxNGFhZTdlZjc5IiwgImZpbHRlcnMiOiBbInVzZXI6bWUiXSwgImlzX3Jlc3RyaWN0ZWQiOiBmYWxzZSwgImVtYWlsX3ZlcmlmaWVkIjogdHJ1ZSwgImVtYWlsIjogImZlYW5pbEBheGltLm9yZyIsICJuYW1lIjogIkZlYW5pbCBQYXRlbCIsICJmYW1pbHlfbmFtZSI6ICIiLCAiZ2l2ZW5fbmFtZSI6ICIiLCAiYWRtaW5pc3RyYXRvciI6IHRydWUsICJzdXBlcnVzZXIiOiB0cnVlfQ.iGFl7qsAUau0-40oq8Of0f72kguq2Hc_drijCnI2I-M',
'expires_in': 3600,
'refresh_token': 'm8iXhVlGABu52xFxVFj5rAz8xSjsRq',
'scope': 'read write email profile',
'token_type': 'JWT'}
Note
The client type must be public
for this to work.
Get a JWT with a client_id and client_secret#
import base64
import requests
from pprint import pprint
client_id = "ukbclQB8aPh7hgsy8ifPXkPf7fRqgUq1w21f2YZa"
# Note this should actually be secret and probably not in your code but
# provided here in the example
client_secret = "xkN0BJ19q9Jk8UPUppEtC1xe4764c81ioFtlegvokbmnAC7CFCT5gG1Og5nnFmCNc3NHNhUwWWDRVcBfnLSZ4xAlEmSePzfkFtLE06cwR1MuSc0gx9LUEjRrTs3j2vgK"
credential = f"{client_id}:{client_secret}"
encoded_credential = base64.b64encode(credential.encode("utf-8")).decode("utf-8")
headers = {"Authorization": f"Basic {encoded_credential}", "Cache-Control": "no-cache"}
data = {"grant_type": "client_credentials", "token_type": "jwt"}
token_request = requests.post(
"http://lms.example.com/oauth2/access_token", headers=headers, data=data
)
pprint(token_request.json())
{'access_token': 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiAibG1zLWtleSIsICJleHAiOiAxNjkyMjExNjM4LCAiZ3JhbnRfdHlwZSI6ICJjbGllbnQtY3JlZGVudGlhbHMiLCAiaWF0IjogMTY5MjIwODAzOCwgImlzcyI6ICJodHRwOi8vbG9jYWxob3N0OjE4MDAwL29hdXRoMiIsICJwcmVmZXJyZWRfdXNlcm5hbWUiOiAiZmVhbmlsIiwgInNjb3BlcyI6IFsicmVhZCIsICJ3cml0ZSIsICJlbWFpbCIsICJwcm9maWxlIl0sICJ2ZXJzaW9uIjogIjEuMi4wIiwgInN1YiI6ICI1YzEwZjY2ZjJkNjM5MGI3MDY2MmM5MTRhYWU3ZWY3OSIsICJmaWx0ZXJzIjogW10sICJpc19yZXN0cmljdGVkIjogZmFsc2UsICJlbWFpbF92ZXJpZmllZCI6IHRydWUsICJlbWFpbCI6ICJmZWFuaWxAYXhpbS5vcmciLCAibmFtZSI6ICJGZWFuaWwgUGF0ZWwiLCAiZmFtaWx5X25hbWUiOiAiIiwgImdpdmVuX25hbWUiOiAiIiwgImFkbWluaXN0cmF0b3IiOiB0cnVlLCAic3VwZXJ1c2VyIjogdHJ1ZX0.CX1S0QGrWKEPOHC8kUzGcvW8Ky04RCA8vU8WJrZURSw',
'expires_in': 3600,
'scope': 'read write email profile',
'token_type': 'JWT'}
Note
When you get a JWT using client_credentials
you don’t get a
refresh token. You’re just expected to make a new call with your client
credentials.
Check to see if a JWT is Expired#
import jwt
# See above examples for how to get a JWT token
jwt_token = token_request.json()['access_token']
try:
jwt.decode(jwt_token, "secret", audience="lms-key", algorithms=['HS256'])
except jwt.ExpiredSignatureError:
# Signature has expired
Refresh a JWT Using a Refresh Token#
import requests
# See "Get a JWT with a Username and Password" for how to get a refresh token.
# The response from that request will include a `refresh_token` attribute.
refresh_token = token_request.json()['refresh_token']
refreshed_token_request = requests.post(
f"http://lms.example.com/oauth2/access_token",
data={
"client_id": "login-service-client-id",
"grant_type": "refresh_token",
"refresh_token": token_request.json()['refresh_token'],
"token_type": "JWT",
},
)
pprint(refreshed_token_request.json())
{'access_token': 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiAibG1zLWtleSIsICJleHAiOiAxNjkyMjE1MTgwLCAiZ3JhbnRfdHlwZSI6ICJwYXNzd29yZCIsICJpYXQiOiAxNjkyMjExNTgwLCAiaXNzIjogImh0dHA6Ly9sb2NhbGhvc3Q6MTgwMDAvb2F1dGgyIiwgInByZWZlcnJlZF91c2VybmFtZSI6ICJmZWFuaWwiLCAic2NvcGVzIjogWyJyZWFkIiwgIndyaXRlIiwgImVtYWlsIiwgInByb2ZpbGUiXSwgInZlcnNpb24iOiAiMS4yLjAiLCAic3ViIjogIjVjMTBmNjZmMmQ2MzkwYjcwNjYyYzkxNGFhZTdlZjc5IiwgImZpbHRlcnMiOiBbInVzZXI6bWUiXSwgImlzX3Jlc3RyaWN0ZWQiOiBmYWxzZSwgImVtYWlsX3ZlcmlmaWVkIjogdHJ1ZSwgImVtYWlsIjogImZlYW5pbEBheGltLm9yZyIsICJuYW1lIjogIkZlYW5pbCBQYXRlbCIsICJmYW1pbHlfbmFtZSI6ICIiLCAiZ2l2ZW5fbmFtZSI6ICIiLCAiYWRtaW5pc3RyYXRvciI6IHRydWUsICJzdXBlcnVzZXIiOiB0cnVlfQ.oNTEk7aMFSjvEbvH_-Gu2QZE93w-CpXSIIuN-IC6BSU',
'expires_in': 3600,
'token_type': 'JWT',
'scope': 'read write email profile',
'refresh_token': 'V5fbgDt2RPVnmI6Q3c6cJ3OjVriGii'}
Use a JWT Header to call an API#
# See above examples for how to get a JWT token
access_token = token_request.json()["access_token"]
enrollment_request = requests.get(
"http://lms.example.com/api/enrollment/v1/enrollment",
headers={"Authorization": f"JWT {access_token}"},
)
pprint(enrollment_request.json())
[{'course_details': {'course_end': None,
'course_id': 'course-v1:TestX+Course+1',
'course_modes': [{'bulk_sku': None,
'currency': 'usd',
'description': None,
'expiration_datetime': None,
'min_price': 0,
'name': 'Audit',
'sku': None,
'slug': 'audit',
'suggested_prices': ''}],
'course_name': 'Open edX Test Course',
'course_start': '2022-04-09T00:00:00Z',
'enrollment_end': None,
'enrollment_start': None,
'invite_only': False,
'pacing_type': 'Instructor Paced'},
'created': '2023-08-17T14:10:48.476967Z',
'is_active': True,
'mode': 'audit',
'user': 'test_user'}]