This repository has been archived by the owner on Mar 30, 2023. It is now read-only.
/
__init__.py
70 lines (58 loc) · 2.72 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
import re
import fnmatch
from browserid.errors import AudienceMismatchError
from browserid.utils import (unbundle_certs_and_assertion,
decode_json_bytes)
class Verifier(object):
"""Abstract base class for verifying BrowserID assertions."""
def __init__(self, audiences=None):
self.audiences = audiences
self._audience_re = self._compile_audience_patterns(audiences)
def verify(self, assertion, audience=None):
"""Verify the given BrowserID assertion.
This method checks the validity of the given BrowserID assertion and,
if valid, returns the dict of asserted data. If it is not valid then
an error will be raised.
If the 'audience' argument is given, the assertion must be for that
specific audience. Otherwise, it must be for an audience matching
one of the patterns provided in the constructor.
"""
raise NotImplementedError
def check_audience(self, assertion, expected_audience=None):
"""Check that the assertion matches the expected audience.
This method verifies that the audience for the given assertion is
as expected - either matching the audience parameter if given, or
or matching one of the audience patterns from the constructor if not.
If the audience matches then it is returned as a string; if not then
an AudienceMismatchError is raised.
"""
try:
_, token = unbundle_certs_and_assertion(assertion)
audience = decode_json_bytes(token.split(".")[1])["aud"]
except (KeyError, IndexError):
raise ValueError("Malformed JWT")
if expected_audience is None:
audience_re = self._audience_re
else:
audience_re = self._compile_audience_patterns(expected_audience)
if audience_re is None:
raise AudienceMismatchError
if not audience_re.match(audience):
raise AudienceMismatchError
return audience
def _compile_audience_patterns(self, audiences):
"""Compile a list of audience patterns into a regular expression."""
if not audiences:
return None
if isinstance(audiences, basestring):
audiences = (audiences,)
regexps = []
for pattern in audiences:
regexp = fnmatch.translate(pattern)
if "://" not in regexp:
regexp = "([a-z]+://)?" + regexp
regexps.append("(" + regexp + ")")
return re.compile("|".join(regexps))