@@ -1149,6 +1149,92 @@ api = ApiClient("https://myapi.local/resource", session=session)
11491149assert api.session == session
11501150```
11511151
1152+ ## Token and Authorization Requests serialization
1153+
1154+ If you implement a web application, you will most likely need to serialize access tokens inside the user session.
1155+ To make it easier, ` requests_oauth2client ` provides several classes that implement (de)serialization.
1156+
1157+ ``` python
1158+ from requests_oauth2client import BearerToken, TokenSerializer
1159+
1160+ token_serializer = TokenSerializer()
1161+
1162+ bearer_token = BearerToken(" access_token" , expires_in = 60 ) # here is a sample token
1163+ serialized_value = token_serializer.dumps(bearer_token)
1164+ print (serialized_value)
1165+ # q1ZKTE5OLS6OL8nPTs1TskLl6iilVhRkFqUWxyeWKFkZmpsZWFiYmJqZ6iiB5eNLKgtSlayUnFITi1KLlGoB
1166+ # you can store that string value in session or anywhere needed
1167+ # beware, this is clear-text!
1168+
1169+ # loading back the token to a BearerToken instance
1170+ deserialized_token = token_serializer.loads(serialized_value)
1171+ assert isinstance (deserialized_token, BearerToken)
1172+ assert deserialized_token == bearer_token
1173+ ```
1174+
1175+ Default ` TokenSerializer ` class supports both ` BearerToken ` and ` DPoPToken ` instances.
1176+
1177+ ``` python
1178+ from requests_oauth2client import AuthorizationRequest, AuthorizationRequestSerializer
1179+
1180+ ar_serializer = AuthorizationRequestSerializer()
1181+
1182+ auth_request = AuthorizationRequest(
1183+ authorization_endpoint = " https://my.as.local/authorize" ,
1184+ client_id = " my_client_id" ,
1185+ redirect_uri = " http://localhost:8000/callback" ,
1186+ )
1187+
1188+ serialized_ar = ar_serializer.dumps(auth_request)
1189+ assert ar_serializer.loads(serialized_ar) == auth_request
1190+ ```
1191+
1192+ ### Customizing token (de)serialization
1193+
1194+ While provided serializers work well for standard tokens with default classes, you may need to override them for special
1195+ purposes or if you are using custom token classes.
1196+ To do that, you can pass custom methods as parameters when initializing your TokenSerializer instance:
1197+
1198+ ``` python
1199+ from __future__ import annotations
1200+
1201+ import base64
1202+ import json
1203+ from typing import Any, Mapping
1204+
1205+ from requests_oauth2client import BearerToken, TokenSerializer
1206+
1207+
1208+ class CustomToken (BearerToken ):
1209+ TOKEN_TYPE = " CustomToken"
1210+
1211+
1212+ def custom_make_instance (args : Mapping[str , Any]) -> BearerToken:
1213+ """ This will add support for a custom token type."""
1214+ if args.get(" token_type" ) == " CustomToken" :
1215+ return CustomToken(** args)
1216+ return TokenSerializer.default_make_instance(args)
1217+
1218+
1219+ def custom_dumper (token : CustomToken) -> bytes :
1220+ """ This will serialize the token value to base64-encoded JSON"""
1221+ args = token.as_dict()
1222+ return base64.b64encode(json.dumps(args).encode())
1223+
1224+
1225+ def custom_loader (serialized : bytes ) -> dict[str , Any]:
1226+ """ This will load from a base64-encoded JSON"""
1227+ return json.loads(base64.b64decode(serialized))
1228+
1229+
1230+ token_serializer = TokenSerializer(make_instance = custom_make_instance, dumper = custom_dumper, loader = custom_loader)
1231+
1232+ my_custom_token = CustomToken(** {" token_type" : " CustomToken" , " access_token" : " ..." })
1233+ serialized = token_serializer.dumps(my_custom_token)
1234+ assert serialized == b ' eyJhY2Nlc3NfdG9rZW4iOiAiLi4uIiwgInRva2VuX3R5cGUiOiAiQ3VzdG9tVG9rZW4ifQ=='
1235+ assert token_serializer.loads(serialized) == my_custom_token
1236+ ```
1237+
11521238## Vendor-Specific clients
11531239
11541240` requests_oauth2client ` is flexible enough to handle most use cases, so you should be able to use any AS by any vendor
0 commit comments