django authentication and password reset - python

So, i am currently working on a web application project and i implemented authentication and password confirmation successfully.
But my issue is that i did it using html templates and now the requirement came up that we have to develop our application using api's for the backened.
Now, i am new to api and really confused how to use the authentication system i built (as we have to provide template to the in-built implemented class and they accept the values from their itself)
Is it possible to actually see and manage the registered users from the code-behind while still using there in-built mechanism

For password change you can use this generic view using the inbuilt Django auth framework
#login_required
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
# Important to update the session otherwise user will have to login again
update_session_auth_hash(request, user)
# Server side alert
print("Password changed for {0}".format(user.username))
return redirect('/index/')
else:
print(form.errors)
else:
form = PasswordChangeForm(request.user)
return render(request, 'website/changepassword.html', {'form': form})
You need to use djangorestframework, and use the decorator #apiview(['GET', 'POST']) to create a RestAPI

You can use TokenAuthentication available in django rest framework. See what documentation says:
TokenAuthentication
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication, and additionally include rest_framework.authtoken in your INSTALLED_APPS setting:
INSTALLED_APPS = (
...
'rest_framework.authtoken'
)
Note: Make sure to run manage.py migrate after changing your settings. The rest_framework.authtoken app provides Django database migrations.
You'll also need to create tokens for your users.
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...)
print token.key
For clients to authenticate, the token key should be included in the Authorization HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
Note: If you want to use a different keyword in the header, such as Bearer, simply subclass TokenAuthentication and set the keyword class variable.
If successfully authenticated, TokenAuthentication provides the following credentials.
request.user will be a Django User instance.
request.auth will be a rest_framework.authtoken.models.Token instance.
Unauthenticated responses that are denied permission will result in an HTTP 401 Unauthorized response with an appropriate WWW-Authenticate header. For example:
WWW-Authenticate: Token
The curl command line tool may be useful for testing token authenticated APIs. For example:
curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
Note: If you use TokenAuthentication in production you must ensure that your API is only available over https.
Source: http://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication

Related

Django REST Custom (token) authentication

Because I'm mixing things up and just making myself more confused, maybe someone can actually guide me through it.
I need to make a Django REST API that requires login. However the User table already exists in a Postgres database. I think token-based authentication is most suitable, however, those tokens don't exist yet.
(Login once to retrieve/create a token, check the token on each request)
How can I use a POST request to submit login details purely for verifying the user?
How would I generate a token upon successful login, and should I store it in a new Token table?
After this, how can I use the token to provide authentication/authorization on API data requests?
All examples I can find use the default Django User model or don't go into enough detail, which I can't use in this case.
I've made a custom authenticator that checks the username and password, however I can't get through the next steps.
from api.models import LogonAccount
from rest_framework import authentication
from rest_framework import exceptions
import bcrypt
class ExampleAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
username = request.data.get('username') # get the username request header
password = request.data.get('password') # get the password request header
if not username or not password: # no username or password passed in request headers
return None # authentication did not succeed
try:
user = LogonAccount.objects.get(username=username)
if bcrypt.hashpw(password.encode(), user.password.encode()):
print("succes")
return (user, None) # authentication successful
except LogonAccount.DoesNotExist:
raise exceptions.AuthenticationFailed('No such user')
Don't get confused, you are simply trying to achieve token-based authentication with DRF. DRF already comes with this feature. This article will guide you through that https://simpleisbetterthancomplex.com/tutorial/2018/11/22/how-to-implement-token-authentication-using-django-rest-framework.html

can I send request to django /admin page?

I'm using django-rest-framework for a simple project. this api doesn't need registration and login for normal users. but it has an admin section on the frontend that can remove or add something to the website(to the database).
Do I need to create a customized ProfileApi App (Login and Authentication App that overrides the default Authentication that django has provided) for having these Possibilities. Or can i send request to /admin url or another url and login and get a token without having trouble of creating another app?
you can use DRF permission class IsAdminUser for these views
class MyAdminView(..):
permission_classes = [IsAdminUser, ]
# rest of view here

How do i programmatically logout user?[Django]

I know to logout user in Django. If i want to logout user, i would do
from django.contrib.auth import logout
def logout_view(request):
logout(request)
But what is the relevant way of logging out the user if i am using django oauth toolkit(DOT)?
Should i follow the same or delete the token? Some says delete the token and some says expiry period should be expired. Please provide me the best possible resolution for logging out in DRF using DOT.
You can check Revoking an OAuth2 Token
You’ve granted a user an Access Token, following part 1 and now you would like to revoke that token, probably in response to a client request (to logout).
And Do you logout a user who login via OAuth2 by expiring their Access Token?
EDIT
# OAuth2 provider endpoints
oauth2_endpoint_views = [
url(r'^authorize/$', oauth2_views.AuthorizationView.as_view(), name="authorize"),
url(r'^token/$', oauth2_views.TokenView.as_view(), name="token"),
url(r'^revoke-token/$', oauth2_views.RevokeTokenView.as_view(), name="revoke-token"),
]
If you follow the tutorial part2 you will find you already have the revoke-token url, so you just need to send request to this url.
EDIT2
Let me try to explain this clearly
When you use Django OAuth Toolkit and DRF, you usually will use
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
)
}
And you can get access token by
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/
And get response like this
{
"access_token": "<your_access_token>",
"token_type": "Bearer",
"expires_in": 36000,
"refresh_token": "<your_refresh_token>",
"scope": "read write groups"
}
Now you can use your access_token to request the api you set like this
curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/users/1/
How to logout depends on how you define login
Website define login from the session in cookies. When you developing a mobile app, You will define login depend on message in your app (user credentials present in keychain or not when it comes to IOS), and that is what your code do:
from django.contrib.auth import logout
def logout_view(request):
logout(request)
You can see source code here django-logout and docs here
flush()
Deletes the current session data from the session and deletes the session cookie. This is used if you want to ensure that the previous session data can’t be accessed again from the user’s browser (for example, the django.contrib.auth.logout() function calls it).
But remember, From Luke Taylor
The lifetime of the access_token is independent of the login session of a user who grants access to a client. OAuth2 has no concept of a user login or logout, or a session, so the fact that you expect a logout to revoke a token, would seem to indicate that you're misunderstanding how OAuth2 works. You should probably clarify in your question why you want things to work this way and why you need OAuth.
Finally In your case, I think you need to revoeke the token before logout:
def revoke-token(request):
# just make a request here
# POST /o/revoke_token/ HTTP/1.1 Content-Type: application/x-www-form-urlencoded token=XXXX&client_id=XXXX&client_secret=XXXX
def logout(request):
response = revoke-toke(request)
# if succeed
logout(request)

Getting Request User on Django Rest Oauth2

I'm using the Django Rest Framework with the Django Oauth Toolkit.
I'm connecting fine. I have no issues with the token, access and permissions.
But I'd like to have a queryset with a filter of the current user something like:
def get_queryset(self):
return Account.objects.filter(user=self.request.user)
When I do this, the user I get is a None Type. Even though I was able to pass correctly the Token via Authorization Bearer.
The oAuth2 application created for this has the following settings:
client type: confidential
authorization grant type: client credentials

How does one ignore CSRF tokens sent to Django REST Framework?

I have a single page angularjs application utilizing JWT authentication. Because JWTs are sent with every single request, it seems redundant to use CSRF tokens in my forms. In order to disable CSRF checking, I commented out 'django.middleware.csrf.CsrfViewMiddleware' in my settings.py middleware classes. This all works fine.
However, when I use the Django Admin panel, CSRF is used. This seems reasonable since JWTs don't protect the Admin pages.
When I log into Admin, a cookie is set containing the CSRF token. When I try to POST to REST endpoints from my angularjs app while logged into an Admin session, the requests contain the CSRF cookie, and the Django REST backend rejects the POST with a 403 status. If I delete the cookie from my browser settings and re-POST, it goes through as expected.
I can configure my app not to set CSRF cookies, but how do I configure my app to ignore the CSRF cookie if it was set by another app on the same domain? I can't guarantee that a token won't be set by something else as I don't control all of the apps that will be running on the domain.
I am using class-based views that extend viewsets in the Django REST Framework. I attempted to address this by decorating my classes with csrf_exempt, but this did not seem to work (still get 403 response). Could I be doing it wrong, or is there some other solution that I am missing?
Here is my attempt at csrf_exempt:
class AccountList(generics.ListCreateAPIView):
serializer_class = serializers.AccountSerializer
def get_queryset(self):
return models.Account.objects.all()
#method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(AccountList, self).dispatch(*args, **kwargs)
It sounds like you have SessionAuthentication enabled, which is the part of Django REST Framework that enforces CSRF for cookie-based authentication. Since you are using JWT, and you mentioned that all pages use JWT for authentication, you should be able to just remove SessionAuthentication from your list of default authentication classes.
If you actually need it, you can just move it to the bottom of the default classes. Because it is detecting the authentication cookies, and authentication was successful, SessionAuthentication will fail before JWT is checked.

Categories

Resources