Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django to return a view with TokenAuthentication for WebView

I am trying to create a flutter app which will use webview to display authenticated data from my Django App.

Steps Involved:

  1. Flutter app sends authentication request
  2. Django validates the user credentials (user id & Password) and returns authtoken
  3. Flutter then sends a request via a webview to a url (which requires login).

I would like to login the user in webapp using this token and return the webview. If the url does not require authentcation, it works like a charm. When the url requires authentication, I am redirected to the login page and I want users to bypass that using token authentication which is already aquired in Step 1

here is my Django view.

class QuizTake(FormView):
    permission_classes = (IsAuthenticated,)
    form_class = QuestionForm
    template_name = 'question.html'
    result_template_name = 'result.html'
    single_complete_template_name = 'single_complete.html'
    login_template_name='login.html'

      
    def dispatch(self, request, *args, **kwargs):
        self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
        print(self.kwargs['quiz_name'])
        
        """
        Authenticate if the request has token authentication
        """

        if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
            raise PermissionDenied

        try:
            self.logged_in_user = self.request.user.is_authenticated()
        except TypeError:
            self.logged_in_user = self.request.user.is_authenticated

        if self.logged_in_user:
            self.sitting = Sitting.objects.user_sitting(request.user,
                                                        self.quiz)
        else:
            self.sitting = self.anon_load_sitting()

        if self.sitting is False:
            print("sitting false")
            if self.logged_in_user:
                return render(request, self.single_complete_template_name)
            else:                
                redirecturl = "/login/?next=/quiz/"+self.kwargs['quiz_name']+"/take/"
                return redirect(redirecturl)
        return super(QuizTake, self).dispatch(request, *args, **kwargs)

Flutter Code

class _QuizLauncherState extends State<QuizLauncher> {
  final String url, authtoken;
  final int userId;
  String quizUrl;
  _QuizLauncherState(this.url,  this.authtoken,this.userId);

  void initState() {
    quizUrl = 'https://test.mysite.com/quiz/$url/take';
    print(quizUrl);
    //for reference https://test.mysite.com/quiz/56df5d90-7f67-45ff-8fe1-7c07728ba9ab/take/
    super.initState();
  }

  Completer<WebViewController> _controller = Completer<WebViewController>();
  final Set<String> _favorites = Set<String>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // This drop down menu demonstrates that Flutter widgets can be shown over the web view.
        actions: <Widget>[
          NavigationControls(_controller.future),
          Menu(_controller.future, () => _favorites),
        ],
      ),          
      body: WebView(
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          Map<String, String> headers = {"Authorization": "Bearer " + authtoken};
          webViewController.loadUrl(quizUrl, headers: headers);
        },

      ),      
    );
  }
}

Is this possible at all? If there are any alternate ways, please tell me. Basically, I am trying to access a url via webview which requires authentication, using authtoken. Please help.

like image 286
stackoverflow rohit Avatar asked Jul 02 '21 14:07

stackoverflow rohit


People also ask

What is Token Authentication in Django rest?

Token authentication refers to exchanging username and password for a token that will be used in all subsequent requests so to identify the user on the server side.This article revolves about implementing token authentication using Django REST Framework to make an API.

What is the default template for authentication views in Django?

Django provides no default template for the authentication views. You should create your own templates for the views you want to use. The template context is documented in each view, see All authentication views. There are different methods to implement these views in your project.

How do I use remote user authentication in Django?

RemoteUserAuthentication This authentication scheme allows you to delegate authentication to your web server, which sets the REMOTE_USERenvironment variable. To use it, you must have django.contrib.auth.backends.RemoteUserBackend(or a subclass) in your AUTHENTICATION_BACKENDSsetting.

Does Django support OAuth2?

Django REST framework OAuth The Django REST framework OAuth package provides both OAuth1 and OAuth2 support for REST framework. This package was previously included directly in REST framework but is now supported and maintained as a third party package.


2 Answers

You can use custom authentication classes like this, say if you are using Authorization header:

from rest_framework.authentication import BaseAuthentication

class MyCustomAuth(BaseAuthentication):
    def authenticate(self, request):
        auth_method, token = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
        # Get your user via the token here
        if you_got_your_user:
            return user, None
        return None # or raise AuthFailedException


class QuizTake(FormView):
    authentication_classes = (MyCustomAuth, )

This still depends on how your token identifies the user though. For example if you are using JWT, there are existing authentication classes already that handles this for you.

EDIT: Looked at knox documentation from here. If you used knox, then you should probably use their own TokenAuthentication class. Can you try with below code:

from knox.auth import TokenAuthentication

class QuizTake(FormView):
    authentication_classes = (TokenAuthentication, )
like image 131
Brian Destura Avatar answered Oct 23 '22 10:10

Brian Destura


You can use authentication from rest framework lib like as below code.

import base64
import binascii
from django.contrib.auth import authenticate, get_user_model
from django.middleware.csrf import CsrfViewMiddleware
from django.utils.translation import gettext_lazy as _
from rest_framework import HTTP_HEADER_ENCODING, exceptions
def get_authorization_header(request):
    auth = request.META.get('HTTP_AUTHORIZATION', b'')
    if isinstance(auth, str):
       auth = auth.encode(HTTP_HEADER_ENCODING)
    return auth
class BaseAuthentication:
      raise NotImplementedError(".authenticate() must be overridden.")
      def authenticate_header(self, request):
          pass
class SessionAuthentication(BaseAuthentication):
      user = getattr(request._request, 'user', None)
      if not user or not user.is_active:
          return None
      self.enforce_csrf(request)
      return (user, None)
def enforce_csrf(self, request):
    def dummy_get_response(request):
    return None
    check = CSRFCheck(dummy_get_response)
    check.process_request(request)
    reason = check.process_view(request, None, (), {})
    if reason:
    raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
class TokenAuthentication(BaseAuthentication):
      keyword = 'Token'
      model = None
      def get_model(self):
          if self.model is not None:
             return self.model
          from rest_framework.authtoken.models import Token
             return Token

Or go through the below link for better understanding [Toke Authorization]

like image 23
Alok Kumar Maurya Avatar answered Oct 23 '22 10:10

Alok Kumar Maurya