Esempio n. 1
0
def test_get_access_token(requests_mock):
    """Test that access token is being requested."""
    token_data = {'access_token': 'example-token'}

    requests_mock.post(
        settings.ADMIN_OAUTH2_TOKEN_FETCH_PATH,
        status_code=status.HTTP_200_OK,
        json=token_data,
    )

    request = get_request_with_session(reverse('admin:index'))
    access_token_data = get_access_token(
        '1234',
        request.build_absolute_uri(reverse('admin_oauth_callback')),
    )

    oauth_params = {
        'code': '1234',
        'grant_type': 'authorization_code',
        'client_id': settings.ADMIN_OAUTH2_CLIENT_ID,
        'client_secret': settings.ADMIN_OAUTH2_CLIENT_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('admin_oauth_callback')),
    }

    assert requests_mock.call_count == 1
    expected_url = f'{settings.ADMIN_OAUTH2_TOKEN_FETCH_PATH}?{urlencode(oauth_params)}'
    assert requests_mock.request_history[-1].url == expected_url

    assert access_token_data == token_data
Esempio n. 2
0
def test_get_access_token_missing(requests_mock):
    """Test that AuthenticationFailed is raised on missing token."""
    requests_mock.post(
        settings.ADMIN_OAUTH2_TOKEN_FETCH_PATH,
        status_code=status.HTTP_200_OK,
        json={},
    )

    request = get_request_with_session(reverse('admin:index'))

    with pytest.raises(AuthenticationFailed) as excinfo:
        get_access_token(
            '1234',
            request.build_absolute_uri(reverse('admin_oauth_callback')),
        )

    assert excinfo.value.detail == 'No access token.'
Esempio n. 3
0
def callback(request):
    """
    OAuth2 callback.

    1. Check if given state matches the state stored in session.
    2. Get access token using provided code.
    3. Request SSO profile using access token.
    4. Find an active user matching SSO profile and having `is_staff` flag.
    5. Store user details in session.
    """
    request_state_id = request.GET.get('state')
    if request_state_id is None:
        # if state is missing then restart login process, include next URL if possible
        redirect_uri = build_redirect_uri(request, reverse('admin:login'))
        return redirect(redirect_uri)

    state_id = request.session['oauth.state']
    if state_id != request_state_id:
        return error_response(request, 'State mismatch.')

    del request.session['oauth.state']

    code = request.GET.get('code')
    if code is None:
        return error_response(request, 'Forbidden.')

    try:
        redirect_uri = build_redirect_uri(request,
                                          reverse('admin_oauth_callback'))
        access_token_data = get_access_token(code, redirect_uri)
        sso_user_profile = get_sso_user_profile(
            access_token_data['access_token'])
        user = get_adviser_by_sso_user_profile(sso_user_profile)
    except AuthenticationFailed as exc:
        logger.warning(f'Django Admin OAuth2 authentication failed: {exc}')
        return error_response(request, 'Forbidden.')

    django_login(request, user)
    request.session['oauth.expires_on'] = int(
        time()) + access_token_data['expires_in']

    next_url = get_safe_next_url_from_request(request)
    if next_url:
        return redirect(next_url)

    return redirect(reverse('admin:index'))