def list(pat: str,
         resource_registration_endpoint: str,
         secure: bool = False) -> List[str]:
    """
    Lists all previously registered resources by ID for this resource owner.
    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - resource_registration_endpoint = URL of the resource registration endpoint in the AS
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        List of IDs (str) registered
    """
    headers = {"Authorization": "Bearer " + pat}

    disable_warnings_if_debug(secure)
    response = request("GET",
                       resource_registration_endpoint,
                       headers=headers,
                       verify=secure)

    if not is_ok(response):
        raise Exception("An error occurred while listing resources: " +
                        str(response.status_code) + ":" +
                        str(response.reason) + ":" + str(response.text))

    return response.json()
def delete(pat: str,
           resource_registration_endpoint: str,
           resource_id: str,
           secure: bool = False):
    """
    Deletes a resource from the AS.
    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - resource_registration_endpoint = URL of the resource registration endpoint in the AS
    - resource_id = ID of the resource
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        Nothing. If no exceptions are raised, the operation completed succesfully.
    """
    headers = {"Authorization": "Bearer " + pat}

    disable_warnings_if_debug(secure)
    response = request("DELETE",
                       resource_registration_endpoint + resource_id,
                       headers=headers,
                       verify=secure)

    if not is_ok(response):
        raise Exception("An error occurred while deleting the resource: " +
                        str(response.status_code) + ":" +
                        str(response.reason) + ":" + str(response.text))
Beispiel #3
0
def introspect(rpt: str, pat: str, introspection_endpoint: str, secure: bool = False) -> dict:
    """
    Gets information about an RPT, using the AS' introspection endpoint.
    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - rpt = String containing the rpt (token)
    - pat = String containing the pat (token)
    - introspection_endpoint = String containing the url to the AS' introspection endpoint
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        JSON-formatted data about the RPT, or an error from the AS
    """

    headers = {
        'content-type': "application/x-www-form-urlencoded",
        'authorization': "Bearer "+pat,
        }

    payload = "token="+rpt

    disable_warnings_if_debug(secure)
    r = request("POST", introspection_endpoint, headers=headers, data=payload, verify=secure)

    if not is_ok(r):
        raise Exception("An error occurred while registering the resource: "+str(r.status_code)+":"+str(r.reason))

    try:
        return r.json()
    except Exception as e:
        raise Exception("Call to introspection point returned unexpected value: "+str(e))
def request_access_ticket(pat: str,
                          permission_endpoint: str,
                          resources: List[dict],
                          secure: bool = False) -> str:
    """
    As a Resource Server, request permission to the AS to access a resource,
    generating a ticket as a result.

    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - permission_endpoint = URL of the token permission endpoint in the AS 
    - resources = List of resources to request permission to.
                            Format:
                            [
                                {
                                    "resource_id": <str resource id>,
                                    "resource_scopes": [ <scope 1>, <scope 2>, ...]
                                },
                                ...
                            ]
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        A string containing the ticket for accessing those resources.
    """

    headers = {
        'content-type': "application/json",
        'authorization': "Bearer " + pat,
    }

    if len(resources) == 1:
        resources = resources[
            0]  # Use a single dict instead of a list for 1 resource

    disable_warnings_if_debug(secure)
    response = request("POST",
                       permission_endpoint,
                       json=resources,
                       headers=headers,
                       verify=secure)

    if not is_ok(response):
        raise Exception(
            "An error occurred while requesting permission for a resource: " +
            str(response.status_code) + ":" + str(response.reason) + ":" +
            str(response.text))

    try:
        return response.json()["ticket"]
    except Exception as e:
        raise Exception(
            "Call to permission endpoint returned unexpected value or error: '"
            + response.text + "'" + ". Error: " + str(e))
def create(pat: str,
           resource_registration_endpoint: str,
           name: str,
           scopes: List[str],
           description: str = None,
           icon_uri: str = None,
           typ: str = None,
           secure: bool = False) -> str:
    """
    Registers a new resource in the AS.
    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - resource_registration_endpoint = URL of the resource registration endpoint in the AS
    - name = Name given to the new resource
    - scopes = List of scopes (strings) assigned to this resource
    - description (Optional) = Description for the resource
    - icon_uri (Optional) = URI to an icon representing this resource
    - typ (Optional) = Type (string/URI) of this resource
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        Resource ID given by the AS associated with the newly created resource, or an error
    """

    payload = {"name": name, "resource_scopes": scopes}
    dict_insert_if_exists(payload, "description", description)
    dict_insert_if_exists(payload, "icon_uri", icon_uri)
    dict_insert_if_exists(payload, "type", typ)

    headers = {
        'Content-Type': "application/json",
        'Authorization': "Bearer " + pat,
    }

    disable_warnings_if_debug(secure)
    response = request("POST",
                       resource_registration_endpoint,
                       json=payload,
                       headers=headers,
                       verify=secure)

    if not is_ok(response):
        raise Exception("An error occurred while registering the resource: " +
                        str(response.status_code) + ":" +
                        str(response.reason) + ":" + str(response.text))

    try:
        return response.json()["_id"]
    except Exception as e:
        raise Exception(
            "Call to registration endpoint returned unexpected value: '" +
            response.text + "'" + ". Error: " + str(e))
Beispiel #6
0
def request_for_rpt(client_creds_token: str,
                    token_endpoint: str, ticket: str,
                    claim_token: str = None, claim_token_format: str = None,
                    scopes: List[str] = None,
                    rpt: str = None,
                    pct: str = None,
                    secure: bool = True) -> dict:
    """
    Requests the AS for an RPT given the arguments used.

    Reference: https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html#uma-grant-type

    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - client_creds_token = token obtained from AS with client credentials
    - token_endpoint = String containing the url to the AS' token endpoint
    - ticket = Ticket obtained from Resource Server for this request
    - claim_token (Optional) = A string containing directly pushed claim information in the indicated format. It MUST be base64url encoded unless specified otherwise by the claim token format
    - claim_token_format (Optional) = If this parameter is used, it MUST appear together with the claim_token parameter. A string specifying the format of the claim token in which the client is directly pushing claims to the authorization server. The string MAY be a URI
    - scopes (Optional) = List of requested scopes
    - rpt (Optional) = A string containing an existing RPT. Allows the Auth Server to upgrade instead of issuing a new RPT.
    - pct (Optional) = A string with an old PCT to optimize looking for a new RPT.
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        A dictionary with at least an access_token and a 'token_type', or an exception
    """
    grant_type = "urn:ietf:params:oauth:grant-type:uma-ticket" # Fixed value according to https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html#uma-grant-type

    headers = {"Authorization": "Basic "+ client_creds_token}

    payload = "grant_type="+grant_type+"&ticket="+ticket
    if claim_token:
        payload+="&claim_token="+claim_token
        # Format only allowed when claim token is given.
        if claim_token_format:
            payload+="&claim_token_format="+claim_token_format
    
    if scopes and len(scopes) > 0:
        payload+="&scope="+" ".join(scopes)
    
    if rpt and len(rpt) > 0:
        payload+="&rpt="+rpt
    if pct and len(pct) > 0:
        payload+="&pct="+pct

    disable_warnings_if_debug(secure)
    response = request("POST", token_endpoint , data=payload, headers=headers, verify=secure)

    if not is_ok(response):
        raise Exception("An error occurred while requesting RPT: "+str(response.status_code)+":"+str(response.reason))

    return response.json()
Beispiel #7
0
    def request_resource(self,
                         uri: str,
                         rpt: str = None,
                         secure: bool = True) -> bytes:
        """
        Requests a resource from the resource server.

        If you have an RPT token for this resource, you can try to re-use it calling
        this function with your RPT, but please notice this function wont try to re-generate
        an RPT via ticket if one is given.

        If you have no RPT but you have initialized this client with the proper credentials,
        this function call will auto-authenticate, handling ticket and RPT calls until the
        resource is obtained.

        - CAN THROW EXCEPTIONS
        - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

        Args:
        - uri = URI to the resource you want to access inside the resource server.
        - rpt (Optional) = String containing the rpt (token)
        - secure (Optional) = toggle checking of SSL certificates. Activating this is recommended on production environments
        
        Returns:
            The resource requested in bytes, or an exception if something went wrong.
        """
        headers = {}
        if rpt:
            headers = {"Authorization": "Bearer " + rpt}

        # Request resource
        ret = request("GET",
                      self.resource_server + uri,
                      headers=headers,
                      secure=secure)

        # Handle ticket
        if ret.status_code == 401:
            rpt = self._handle_ticket_request(ret)
            # Re-try with an rpt obtained from ticket
            return self.request_resource(uri, rpt, secure)

        # Any error other than a 401 is an error that this client cannot automatically solve
        elif not is_ok(ret):
            raise Exception(
                "Resource server denied access with an unexpected error: " +
                str(ret.status_code) + ": " + str(ret.reason))

        # Return resource when access is achieved
        return ret.content
def read(pat: str,
         resource_registration_endpoint: str,
         resource_id: str,
         secure: bool = False) -> dict:
    """
    Reads the information for a single resource, indicated by resource ID.

    Note that if an empty resource ID is given, this function is identical to 'list()', but please use each function
    for their respective intended use as this behaviour is not intended by design and may change at any time

    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - resource_registration_endpoint = URL of the resource registration endpoint in the AS
    - resource_id = ID of the resource on the AS
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        JSON-formatted information about the resource
    """
    headers = {"Authorization": "Bearer " + pat}

    disable_warnings_if_debug(secure)
    if resource_registration_endpoint[-1] is not "/":
        resource_registration_endpoint += "/"

    response = request("GET",
                       resource_registration_endpoint + resource_id,
                       headers=headers,
                       verify=secure)
    if not is_ok(response):
        raise Exception(
            "An error occurred while getting a resource's information: " +
            str(response.status_code) + ":" + str(response.reason) + ":" +
            str(response.text))

    return response.json()
def update(pat: str,
           resource_registration_endpoint: str,
           resource_id: str,
           name: str,
           scopes: List[str],
           description: str = None,
           icon_uri: str = None,
           typ: str = None,
           secure: bool = False) -> str:
    """
    Updates one or more aspects of the resource indicated by id.
    
    The entirety of the resource will be overwritten with these values as per UMA 2.0's standard.
    https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-federated-authz-2.0.html#update-resource-set
 
    - CAN THROW EXCEPTIONS
    - MAKES A CONNECTION TO AN EXTERNAL ENDPOINT

    Args:
    - pat = String containing the pat (token)
    - resource_registration_endpoint = URL of the resource registration endpoint in the AS
    - resource_id = ID of the resource
    - name (Optional) = Name given to the new resource
    - scopes (Optional) = List of scopes (strings) assigned to this resource
    - description (Optional) = Description for the resource
    - icon_uri (Optional) = URI to an icon representing this resource
    - typ (Optional) = Type (string/URI) of this resource
    - secure = toggle checking of SSL certificates. Activating this is recommended on production environments
    
    Returns:
        Resource ID given by the AS associated with the edited resource
    """
    payload = {}
    dict_insert_if_exists(payload, "name", name)
    dict_insert_if_exists(payload, "resource_scopes", scopes)
    dict_insert_if_exists(payload, "description", description)
    dict_insert_if_exists(payload, "icon_uri", icon_uri)
    dict_insert_if_exists(payload, "type", typ)

    if len(payload) == 0:
        raise Exception(
            "No attribute to update the resource with, payload empty")

    headers = {
        'content-type': "application/json",
        'authorization': "Bearer " + pat,
    }

    disable_warnings_if_debug(secure)
    response = request("PUT",
                       resource_registration_endpoint + resource_id,
                       json=payload,
                       headers=headers,
                       verify=secure)

    if not is_ok(response):
        raise Exception("An error occurred while registering the resource: " +
                        str(response.status_code) + ":" +
                        str(response.reason) + ":" + str(response.text))

    try:
        return response.json()["_id"]
    except Exception as e:
        raise Exception(
            "Call to registration endpoint returned unexpected value: '" +
            response.text + "'" + ". Error: " + str(e))