@@ -132,6 +132,8 @@ class Client(BaseClient): # We choose to implement all 4 grants in 1 class
132132 "DEVICE_CODE" : "device_code" ,
133133 }
134134 DEVICE_FLOW_RETRIABLE_ERRORS = ("authorization_pending" , "slow_down" )
135+ GRANT_TYPE_SAML2 = "urn:ietf:params:oauth:grant-type:saml2-bearer" # RFC7522
136+ GRANT_TYPE_JWT = "urn:ietf:params:oauth:grant-type:jwt-bearer" # RFC7523
135137
136138 def initiate_device_flow (self , scope = None , ** kwargs ):
137139 # type: (list, **dict) -> dict
@@ -348,3 +350,23 @@ def obtain_token_with_refresh_token(self, token_item, scope=None,
348350 return resp
349351 raise ValueError ("token_item should not be a type %s" % type (token_item ))
350352
353+ def obtain_token_with_assertion (
354+ self , assertion , grant_type = None , scope = None , ** kwargs ):
355+ # type: (str, Union[str, None], Union[str, list, set, tuple]) -> dict
356+ """This method implements Assertion Framework for OAuth2 (RFC 7521).
357+ See details at https://tools.ietf.org/html/rfc7521#section-4.1
358+
359+ :param assertion: The assertion string which will be sent on wire as-is
360+ :param grant_type:
361+ If you leave it as the default None, this method will try to make
362+ a guess between SAML2 (RFC 7522) and JWT (RFC 7523),
363+ the only two profiles defined in RFC 7521.
364+ But you can also explicitly provide a value, if needed.
365+ :param scope: Optional. It must be a subset of previously granted scopes.
366+ """
367+ if grant_type is None :
368+ grant_type = self .GRANT_TYPE_JWT if "." in assertion else self .GRANT_TYPE_SAML2
369+ data = kwargs .pop ("data" , {})
370+ data .update (scope = scope , assertion = assertion )
371+ return self ._obtain_token (grant_type , data = data , ** kwargs )
372+
0 commit comments