A Command Line Client¶
UNDER CONSTRUCTION
See jsonapi_demo_cli
.
This client demonstrates a rudimentary Python command-line tool that interacts with our demo JSONAPI project.
It:
1. performs an OAuth 2.0 login to acquire the Bearer token. If the type of OAuth 2.0 grant
requires a browser login, a browser window is opened to perform the login.
2. uses the jsonapi-requests
library
to do a few queries.
This demo client is overly complicated (I couldn't resist;-) as it automates the web browser popup and callback handling for the Authorization Code or Implicit grants. Below is a simplified description of the key stuff you will likely actually need to do if you are writing a "headless" backend client, probably to implement some sort of "batch" activities where the client backend is trusted (rather than needing an end-user to login).
Oauth 2.0 Login¶
The first step is to end up with a "bearer" Access Token that gets put into the Authorization
header.
Using oauthlib you first initialize the library, which differs
based on the type of grant. You'll want to include a list of requested scopes based on what the Resource Server
(our demo DJA app) requires.
There are a number of OAuth 2.0/Openid Connect 1.0 client libraries. I've chosen just to base this example on oauthlib.
TODO: There's also integrated OAuth client support in requests-oauthlib including automated token refresh.
OAuth 2.0 Service Endpoints¶
You need to know the various endpoints of the OAuth2 server. You can hard code them or query the
server itself via the /.well-known/openid-configuration
URL.
1 2 3 4 5 6 7 |
|
Oauth 2.0 Client Basic Auth¶
In most all cases you need to use HTTP Basic Auth to authenticate your client to the OAuth 2.0 Authorization Server
using pre-registered client credentials (client_id
and client_secret
). This creates an HTTP header
that looks like Authorization: Basic YWRtaW46YWRtaW4xMjM=
.
The standard Python requests
library has an HTTPBasicAuth()
function that does the right thing.
1 2 3 4 |
|
A Backend (Client Credentials) Client¶
A "backend" client uses a very simple OAuth 2.0 grant: Client Credentials -- which uses the
OAuth 2.0 token
endpoint.
Use an instance of oauthlib's BackendApplicationClient
to prepare_token_request()
and post it.
(The oauthlib prepare_*
functions fill in everything needed for the HTTP request except the
authorization info, which we've already set up, above.)
1 2 3 4 5 6 7 |
|
1 2 3 4 5 |
|
1 2 |
|
JSONAPI client¶
There are a number of JSONAPI client libraries available for many languages. You can also just directly manipulate the JSON responses and requests as we did in the examples with Postman.
The examples use jsonapi-requests which has both an ORM and raw (non-ORM) style. Let's start with the ORM style. You'll have to define your classes but then operations are really easy, looking similar to Django's model managers.
ORM Style¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
Sample exeution of the above:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
|
N.B. Each RelationField you create must have a corresponding class definition or you'll get a key error.
Raw (non-ORM) Style¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
See the demo app source code for more sophisticated ORM operations.
Following is a sample execution of the above code snippets. Your mileage may vary based on what data is in your resource server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
|
Installing and running the demo client¶
Make sure you have a local pypi repo that has this package installed and:
pip install demo-jsonapi-cli
Or, if you don't have the repo:
1 |
|
1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Example¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
|
TODO¶
- Mash up
jsonapi_requests
withrequests_oauthlib
perhaps using https://github.com/jd/tenacity#custom-callbacks (whichjsonapi_requests
already uses) to automate using a refresh token to get a new access token when the old one expires. - Look at
jsonapi_client
as an alternative tojsonapi_requests
.