~jamestait/rnr-server/sca-conn-check-301

« back to all changes in this revision

Viewing changes to src/core/api/auth/macaroon.py

  • Committer: Tarmac
  • Author(s): Ricardo Kirkner
  • Date: 2016-05-17 14:37:37 UTC
  • mfrom: (316.1.11 trunk)
  • Revision ID: tarmac-20160517143737-upuntzyo0kv78mzg
[r=fgallina] support submitting reviews using macaroon based authentication

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#   This file is part of Software Center Ratings and Reviews
 
2
#   Copyright (C) 2016 Canonical Ltd.
 
3
#
 
4
#   This program is free software: you can redistribute it and/or modify
 
5
#   it under the terms of the GNU Affero General Public License as
 
6
#   published by the Free Software Foundation, either version 3 of the
 
7
#   License, or (at your option) any later version.
 
8
#
 
9
#   This program is distributed in the hope that it will be useful,
 
10
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
#   GNU Affero General Public License for more details.
 
13
#
 
14
#   You should have received a copy of the GNU Affero General Public License
 
15
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 
 
17
"""Macaroon authenticator for Piston."""
 
18
 
 
19
from __future__ import absolute_import
 
20
 
 
21
import logging
 
22
 
 
23
from django.http import HttpResponse
 
24
from piston.authentication import OAuthAuthentication
 
25
 
 
26
from core.utilities import (
 
27
    update_or_create_user_from_sso,
 
28
    web_services,
 
29
)
 
30
 
 
31
 
 
32
logger = logging.getLogger(__name__)
 
33
 
 
34
 
 
35
def has_macaroon_bits(authorization):
 
36
    """Return whether there are Macaroon bits in authorization.
 
37
 
 
38
    Macaroon bits are detected by ensuring the authorization starts with
 
39
    'Macaroon'.
 
40
 
 
41
    """
 
42
    has_bits = (
 
43
        authorization and authorization.split()[0].lower() == 'macaroon')
 
44
    return has_bits
 
45
 
 
46
 
 
47
class MacaroonsAuthentication(OAuthAuthentication):
 
48
    """ This class is a Piston Authentication class.
 
49
 
 
50
    See http://bitbucket.org/jespern/django-piston/wiki/Documentation for
 
51
    more info.
 
52
    """
 
53
    def __init__(self, realm='API'):
 
54
        self.realm = realm
 
55
 
 
56
    def challenge(self):
 
57
        """ We define our own challenge so that we can provide our own realm
 
58
        and return a simple error message instead of rendering a template.
 
59
        """
 
60
        resp = HttpResponse("Authorization Required")
 
61
        resp['WWW-Authenticate'] = 'Macaroon realm="%s"' % self.realm
 
62
        resp.status_code = 401
 
63
        return resp
 
64
 
 
65
    def is_authenticated(self, request):
 
66
        authorization = request.META.get('HTTP_AUTHORIZATION', None)
 
67
        if not has_macaroon_bits(authorization):
 
68
            # skip network request as macaroon headers are missing
 
69
            return False
 
70
        data = web_services.verify_acl(request)
 
71
        account = data and data.get('account', {}) or {}
 
72
        verified = account.get('verified', False)
 
73
        if not verified:
 
74
            return False
 
75
 
 
76
        # get or create user account
 
77
        user, _ = update_or_create_user_from_sso(
 
78
            account.get('openid'), account=account)
 
79
 
 
80
        # inject user into request
 
81
        request.user = user
 
82
        return True