Clone Blango Repo Clone Blango Repo: in The Terminal
Clone Blango Repo Clone Blango Repo: in The Terminal
Clone Blango Repo Clone Blango Repo: in The Terminal
Blango Repo
In the Terminal
Clone the repo. Your command should look something like this:
Authentication
Intro
One aspect that has been distinctly lacking from out API views so far is
authentication - anyone can perform any action on the API. Obviously that
is not ideal! Especially since one of the pillars of Django is its security.
When dealing with user access to the API, there are actually two pieces:
authentication, which is who you are; and permissions, which is what you
are allowed to do.
We’ll look at authentication first, and three methods that Django Rest
Framework provides for us to authenticate.
Using session authentication is not ideal for use with an API. With a REST
API it’s useful for the client to be able to tell who the current user is, by
looking at the request. This information isn’t that obvious when looking at
a session identifier (a random string) which can’t be related to a user. In
addition, the session might store extra information in the backend which
can alter the response we get, so doing the same response more that once
might unexpectedly return different data that is retrieved from the session.
And finally, most HTTP clients designed for API usages aren’t set up to store
cookie data so this is something you’d have to manage manually.
However, when testing the API with the DRF browser GUI, session
authentication works quite well, because it automatically works with forms
and the browser will store the cookie automatically.
We already have two ways of logging into Blango, either with the Django
Admin page at /admin/ or with the standard user login page at
/accounts/login/.
If we didn’t already have login pages set up, DRF provides one we can use.
We just need to include the rest_framework.urls URL patterns and DRF
does the work.
urlpatterns += [
path("auth/", include("rest_framework.urls")),
]
The path can actually be anything we want, DRF uses the Django URL
reversing functionality to check if its views are set up.
Then, DRF will detect that you have the login URL configured and
automatically add a link to log in in the top right corner of a DRF view
page.
log in link
After clicking the link you’ll see the DRF login page.
Logging in here should behave the same as logging in with any of our other
forms. You’ll get redirect back to the DRF page you came from, and see your
email address in the top right corner, indicating that you’re logged in.
Try it out
Let’s add the DRF auth URLS to Blango, so our API users have an easy way
to find a login page.
Follow the instructions just above to add the import of include and extra
urlpatterns to blog/api/urls.py.
Then, load up one of the Blango DRF API views. You should see a Log in
link in the top right corner. Or, if you’re already logged in, a dropdown
menu with a Log out link.
View Blog
Next we’ll look at basic authentication, which is more useful for REST APIs.
Basic Authentication
Basic authentication
Basic authentication is more useful that session authentication when it
comes to REST APIs. Although it does have some drawbacks, which we’ll
cover when we cover token authentication. Basic authentication involves
sending the username and password with each request. These are joined
by a :, then base-64 encoded, and sent in the Authorization header. The
username username and password password would be sent like this:
We can easily set up Postman to use Basic authentication. Let’s do that now.
Try it out
You can now configure Postman to use basic authentication. Open Postman,
and select the Blango collection from the collections list (not the Posts
folder or any of the requests in the folder). Then, on the right the
Authorization tab should be selected, but click on it if it’s not.
You can test that it’s working by making a request using Postman.
Everything should work the same as it did previously. If you’ve put in an
incorrect username (email address) or password, you’ll get a response with
a 403 status code and an error response body:
{"detail":"Invalid username/password."}
Even though none of our API views require authentication, DRF still
automatically validates credentials for us, if provided.
To provide HTTP basic auth using the requests framework, we can use the
requests.auth.HTTPBasicAuth class. Be sure to start the Python shell before
continuing.
After the shell is running, import requests and then import HTTPBasicAuth.
In [1]: import requests
In [2]: from requests.auth import HTTPBasicAuth
info
https://martin-volume-8000.codio.io/api/v1/posts/
Once you have your correct URL, make a request wit incorrect information.
In [3]: requests.get("https://martin-volume-
8000.codio.io/api/v1/posts/",
auth=HTTPBasicAuth("user@example.com", "badpassword"))
In [4]: requests.get("https://martin-volume-
8000.codio.io/api/v1/posts/",
auth=HTTPBasicAuth("patrick@example.com", "password"))
We’ll cover the use of requests to connect to third party APIs in the fourth
course.
Basic authentication has some drawbacks. If a user has one user account
but wants to access it from many API clients, they all share credentials. This
means if a user wants to access an API with a third party service that they
might not fully trust, they have to give that service their username and
password. If that service were run by someone malicious they could take
that username and password and log into our system will full access.
On the backend, we don’t have an easy way to figure out which specific
service is making API requests as they all share the same credentials. This
also means we can’t specifically rate-limit or disable access to a particular
bad client/service without completely blocking that user.
Token authentication
Token authentication works by passing a token (a long, random string) in
the Authorization header. The backend server can then map the token
back to a user and authenticate them without a username and password.
This means that:
DRF’s built in token system doesn’t solve all these issues, as it only allows
one token per user, but in Course 3 we’ll look at JSON Web Tokens which
are more flexible.
When using a token, the Authorization HTTP header looks like this:
Authorization: Token
fccdf7307189644e9fee624224d3471d870a7b829f5c23d0297f15e34c41b974
The keyword Token describes what kind of authorization is being used. You
might also see the word Bearer being used.
DRF tokens are stored in the database, as a Token model object, so we have
a few options for creating them.
The first method is through Python code: just import the Token model from
rest_framework.authtoken.models and create() a new instance. The token
“key” (the string sent in the Authorization header) is automatically
generated on create.
Then after saving, we’ll see the key for that user’s Token.
Finally, DRF provides a view we can use to get or retrieve a token for a
user: rest_framework.authtoken.views.obtain_auth_token. To set this up
we just need to add a URL for it. For example, in Blango’s api/urls.py file,
add the import:
urlpatterns += [
path("auth/", include("rest_framework.urls")),
path("token-auth/", views.obtain_auth_token)
]
URL Prefix
Remember the prefix on our API URLs: the full path to the
obtain_auth_token view is /api/v1/token-auth.
{"token":"81082614a73f331b122ba93dbdb5951b44cf21d4"}
Try It Out
Try it out
We’ll get the token authentication set up in Blango now. Start by opening
the settings.py file and add the REST_FRAMEWORK setting, currently just
containing authentication classes settings.
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.BasicAuthentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
]
}
You’ll then need to run manage.py migrate to add the Token model to the
database.
As we’ve seen, there are lots of way to set up a token for a user, but we’ll
try out creating one using the API itself. This means setting up the
obtain_auth_token view.
Open api/urls.py
urlpatterns += [
path("auth/", include("rest_framework.urls")),
path("token-auth/", views.obtain_auth_token)
]
Now, you can try it out in Postman. Create a new POST request inside the
Blango collection. The URL should be {{base_url}}token-auth/. Create a
JSON request body with username (the user’s email address) and password.
Try out the request, and you should get a response with a token.
Figure 8
How can we use this token in Postman? Select the Blango collection on the
left, and then the Authorization tab. Select the type API Key. The values to
use are:
Key: Authorization
Value: Token <your token>, e.g. Token
81082614a73f331b122ba93dbdb5951b44cf21d4
Add to: Header
You should still be able to make requests as you did before. You can
validate that the token authentication is working by trying to put in an
incorrect token. In this case, your requests will return responses like this:
{"detail":"Invalid token."}
To pass the token in the Authorization header using the requests library,
we pass it in the headers dictionary:
requests.get("http://127.0.0.1:8000/api/v1/posts/", headers=
{"Authorization": "Token
81082614a73f331b122ba93dbdb5951b44cf21d4"})
<Response [200]>
class PostList(generics.ListCreateAPIView):
authentication_classes = [SessionAuthentication]
# other methods/attributes truncated for brevity
In the next section we’ll look at adding some permissions to our DRF API
views.
Pushing to GitHub
Pushing to GitHub
Before continuing, you must push your work to GitHub. In the terminal:
git add .
git commit -m "Finish authentication"
Push to GitHub:
git push