55
66from models .errors import UnauthorizedError
77
8- PERMISSIONS_HEADER = "Permissions"
8+
99AUTHENTICATION_HEADER = "AuthenticationType"
1010
1111
@@ -14,40 +14,16 @@ class UnknownPermission(RuntimeError):
1414 """Error when the parsed value can't be converted to Permissions enum."""
1515
1616
17- class EndpointOperation (Enum ):
18- """The kind of operation.
19- This maps one-to-one to each endpoint. Authorization class decides whether there are sufficient permissions or not.
20- The caller is responsible for passing the correct operation.
21- """
22- READ = 0 ,
23- CREATE = 1 ,
24- UPDATE = 2 ,
25- DELETE = 3 ,
26- SEARCH = 4 ,
27-
28-
2917class AuthType (str , Enum ):
3018 """This backend supports all three types of authentication.
3119 An Apigee App should specify AuthenticationType in its custom attribute.
3220 Each Apigee app can only have one type of authentication which is enforced by onboarding process.
3321 See: https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation"""
3422 APP_RESTRICTED = "ApplicationRestricted" ,
35- NHS_LOGIN = "NnsLogin " ,
23+ NHS_LOGIN = "NhsLogin " ,
3624 CIS2 = "Cis2" ,
3725
3826
39- class Permission (str , Enum ):
40- """Permission name for each operation that can be done to an Immunization Resource
41- An Apigee App should specify a set of these as a comma-separated custom attribute.
42- Permission works the same way as 'scope' but, in this case, they're called permission to distinguish them from
43- OAuth2 scopes"""
44- READ = "immunization:read"
45- CREATE = "immunization:create"
46- UPDATE = "immunization:update"
47- DELETE = "immunization:delete"
48- SEARCH = "immunization:search"
49-
50-
5127class Authorization :
5228 """ Authorize the call based on the endpoint and the authentication type.
5329 This class uses the passed headers from Apigee to decide the type of authentication (Application Restricted,
@@ -56,52 +32,13 @@ class Authorization:
5632 UnknownPermission is due to proxy bad configuration, and should result in 500. Any invalid value, either
5733 insufficient permissions or bad string, will result in UnauthorizedError if it comes from user.
5834 """
59-
60- def authorize (self , operation : EndpointOperation , aws_event : dict ):
35+
36+ def authorize (self , aws_event : dict ):
6137 auth_type = self ._parse_auth_type (aws_event ["headers" ])
62- if auth_type == AuthType .APP_RESTRICTED :
63- self ._app_restricted (operation , aws_event )
64- if auth_type == AuthType .CIS2 :
65- self ._cis2 (operation , aws_event )
66- # TODO(NhsLogin_AMB-1923) add NHSLogin
67- else :
68- UnauthorizedError ()
69-
70- _app_restricted_map = {
71- EndpointOperation .READ : {Permission .READ },
72- EndpointOperation .CREATE : {Permission .CREATE },
73- EndpointOperation .UPDATE : {Permission .UPDATE , Permission .CREATE },
74- EndpointOperation .DELETE : {Permission .DELETE },
75- EndpointOperation .SEARCH : {Permission .SEARCH },
76- }
77-
78- def _app_restricted (self , operation : EndpointOperation , aws_event : dict ) -> None :
79- allowed = self ._parse_permissions (aws_event ["headers" ])
80- requested = self ._app_restricted_map [operation ]
81- if not requested .issubset (allowed ):
38+
39+ if auth_type not in {AuthType .APP_RESTRICTED , AuthType .CIS2 , AuthType .NHS_LOGIN }:
8240 raise UnauthorizedError ()
8341
84- def _cis2 (self , operation : EndpointOperation , aws_event : dict ) -> None :
85- # Cis2 works exactly the same as ApplicationRestricted
86- self ._app_restricted (operation , aws_event )
87-
88- @staticmethod
89- def _parse_permissions (headers ) -> Set [Permission ]:
90- """Given headers return a set of Permissions. Raises UnknownPermission"""
91-
92- content = headers .get (PERMISSIONS_HEADER , "" )
93- # comma-separate the Permissions header then trim and finally convert to lowercase
94- parsed = [str .strip (str .lower (s )) for s in content .split ("," )]
95-
96- permissions = set ()
97- for s in parsed :
98- try :
99- permissions .add (Permission (s ))
100- except ValueError :
101- raise UnknownPermission ()
102-
103- return permissions
104-
10542 @staticmethod
10643 def _parse_auth_type (headers ) -> AuthType :
10744 try :
@@ -112,14 +49,13 @@ def _parse_auth_type(headers) -> AuthType:
11249 # we raise UnknownPermission in case of an error and not UnauthorizedError
11350 raise UnknownPermission ()
11451
115-
116- def authorize (operation : EndpointOperation ):
52+ def authorize ():
11753 def decorator (func ):
11854 auth = Authorization ()
11955
12056 @wraps (func )
12157 def wrapper (controller_instance , a ):
122- auth .authorize (operation , a )
58+ auth .authorize (a )
12359 return func (controller_instance , a )
12460
12561 return wrapper
0 commit comments