Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why HttpResponseRedirect.set_cookie is not working when i use in django project?

Tags:

cookies

django

When I use Google OAuth to verify my user, After verify is passed, I want to redirect to the page which user visit before authority, So I want to save the page path to user's cookie, so I implementation like this:

def get_login_resp(request, redirect):
    print(redirect)
    auth_url = "https://accounts.google.com/o/oauth2/auth?" + urlencode({
        "client_id": GOOGLE_CLIENT_ID,
        "response_type": "code",
        "redirect_uri": make_redirect_url(request, redirect),
        "scope": "profile email",
        "max_auth_age": 0
    })
    resp = HttpResponseRedirect(auth_url)
    max_age = 3600 * 24
    expires = datetime.strftime(datetime.utcnow() + timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT")
    print(expires)
    resp.set_cookie('google_auth_redirect', redirect, max_age=max_age, expires=expires,
                    domain=LOGIN_COOKIE_DOMAIN, secure=True, httponly=True)
    print(resp._headers)
    print(resp.cookies)
    return resp

ps: redirect is the page path which I want to save

But when request the login url with Postman, I can only see this headers: response headers

And these cookies: Cookies

So how can i do with this problem? There is not any error info for me.

like image 654
Leekin Avatar asked Oct 19 '25 10:10

Leekin


1 Answers

Try every methods to find out what's wrong, But still failed.

So I try to run server on an other machine(a Linux server), it works!!!

BTW: My develop PC is Macbook Pro 15-inch, 2017 with macOS High Sierra 10.13.1

Update at 14/Jan/2020:

Didn't find the root cause, but I solved this issue by saving redirect_url to session data, in this solution you should check auth valid by using another request, then call google auth to reauth again, code like below:

class GoogleAuthView(RedirectView):
# google auth view

    def get(self, request, *args, **kwargs):
        # get redirect url from url params, frontend code should pass the param in request url
        redirect_url = request.GET.get('redirect_url', None)
        if redirect_url:
            redirect_url = parse.unquote(redirect_url)
        credentials = request.session.get("credentials", None)
        if (not credentials) or ('expire_time' not in credentials) or (credentials['expire_time'] < time.time()):
            request.session['redirect_url'] = redirect_url  # if need google auth, save redirect url to session first
        else:
            if redirect_url:
                return HttpResponseRedirect(redirect_url)

        flow = google_auth_oauthlib.flow.Flow.from_client_config(
            client_config=settings.GOOGLE_AUTH_CONFIG,
            scopes=settings.GOOGLE_AUTH_SCOPES
        )
        flow.redirect_uri = settings.GOOGLE_AUTH_CONFIG['web']['redirect_uris'][0]
        authorization_url, state = flow.authorization_url(
            access_type='offline',
            include_granted_scopes='true'
        )
        request.session['state'] = state
        return HttpResponseRedirect(authorization_url)


class GoogleAuthCallBackView(BasicView):
# google callback view

    def get(self, request, *args, **kwargs):
        state = request.session.get('state')
        flow = google_auth_oauthlib.flow.Flow.from_client_config(
            client_config=settings.GOOGLE_AUTH_CONFIG,
            scopes=settings.GOOGLE_AUTH_SCOPES,
            state=state
        )
        flow.redirect_uri = settings.GOOGLE_AUTH_CONFIG['web']['redirect_uris'][0]

        # get redirect url from session data if exists
        redirect_url = request.session.get('redirect_url') or settings.ADMIN_LOGIN_REDIRECT_URL
        response = HttpResponseRedirect(redirect_url)
        try:
            del request.session['redirect_url']
        except KeyError:
            logger.info('Delete `redirect_url` in session get KeyError.')
            pass

        try:

            flow.fetch_token(authorization_response=request.build_absolute_uri())
        except Exception as e:
            logger.error(e.message)
            return response

        # save credentials to session
        credentials = flow.credentials
        request.session["credentials"] = {
            'token': credentials.token,
            'refresh_token': credentials.refresh_token,
            'token_uri': credentials.token_uri,
            'client_id': credentials.client_id,
            'client_secret': credentials.client_secret,
            'scopes': credentials.scopes,
            'expire_time': time.time() + TOKEN_EXPIRE_TIME,
        }

        profile_client = googleapiclient.discovery.build(
            serviceName='oauth2',
            version='v2',
            credentials=credentials
        )

        profile = profile_client.userinfo().v2().me().get().execute()
        email = profile['email']
        user = user_manager.get_user_by_email(email)

        if user:
            user.username = profile['name']  # sync username from google
            user.picture = profile['picture']  # sync avatar from google
            user.save()
            request.session["user"] = user.to_dict()
        else:
            return HttpResponseRedirect("/api/non_existent_user/")  # show non-existent user

        return response
like image 133
Leekin Avatar answered Oct 22 '25 01:10

Leekin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!