# By: Riasat Ullah
# This file contains constants, variables and functions for handling SSO.

from taskcallweb import settings
from utils import s3


# s3 bucket details for retrieving SSO credentials
s3_sso_bucket = 'taskcall-prod-data'
s3_sso_key = 'credentials/sso_credentials.json'

# redirect urls
taskcall_azure_sso_redirect_uri = settings.REDIRECT_BASE + '/login/sso/azure'
taskcall_google_sso_redirect_uri = settings.REDIRECT_BASE + '/login/sso/google'
taskcall_okta_redirect_uri = settings.REDIRECT_BASE + '/login/sso/okta'

# internal variable names - for storing values in session, etc
var_google_discovery_data = 'google_discovery_data'
var_okta_client_id = 'okta_client_id'
var_okta_client_secret = 'okta_client_secret'
var_okta_introspection_endpoint = 'okta_introspection_endpoint'
var_okta_token_endpoint = 'okta_token_endpoint'
var_saml_settings = 'saml_settings'

###########################
# Azure SSO
###########################
# url paths
azure_discovery_url = 'https://login.microsoftonline.com/{0}/v2.0/.well-known/openid-configuration'
azure_oauth_url = '{0}?response_type=id_token&client_id={1}&scope=openid+profile+email' +\
                  '&redirect_uri={2}&response_mode=form_post&state={3}&nonce={4}&domain_hint={5}'

###########################
# Google SSO
###########################
# url paths
google_discovery_url = 'https://accounts.google.com/.well-known/openid-configuration'
google_oauth_url = '{0}?response_type=code&client_id={1}&scope=openid%20email%20profile' +\
                   '&redirect_uri={2}&state={3}&hd={4}'

###########################
# Okta
###########################
# url paths
okta_discovery_url = 'https://{0}/.well-known/openid-configuration'
okta_oauth_url = '{0}?client_id={1}&response_type=code&scope=openid%20email%20profile' +\
                 '&redirect_uri={2}&state={3}'

# variable names
var_authorization_endpoint = 'authorization_endpoint'
var_id_token = 'id_token'
var_introspection_endpoint = 'introspection_endpoint'
var_token_endpoint = 'token_endpoint'


def get_sso_credentials(sso_type):
    '''
    Get the SSO credentials and other necessary information from s3.
    :param sso_type: the type of SSO
    :return: details of the SSO
    '''
    try:
        data = s3.read_json(s3_sso_bucket, s3_sso_key)
        return data[sso_type]
    except KeyError as e:
        err = 'Unknown sso type - ' + sso_type + '\n' + str(e)
        raise KeyError(err)
    except (OSError, IOError) as e:
        err = 'Could not read sso credentials file' + '\n' + str(e)
        raise OSError(err)


def is_azure_csrf_exempt_origin(path: str):
    '''
    Checks if a given path is exempt from csrf checks for azure ad sso.
    :param path: url path
    :return: (boolean) True if the path is exempt; False otherwise
    '''
    exempt_origin_paths = ['https://login.microsoftonline.com']
    if path.rstrip('/') in exempt_origin_paths:
        return True
    return False


def get_saml_settings(entity_id, acs_url, saml_certificate, saml_login_url, issue_url=None):
    return {
        'idp': {
            'entityId': issue_url if issue_url is not None else '',
            'singleSignOnService': {
                'url': saml_login_url,
                'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
            },
            'x509cert': saml_certificate
        },
        'sp': {
            'entityId': entity_id,
            'assertionConsumerService': {
                'url': acs_url,
                'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
            },
            'NameIDFormat': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
        },
        'security': {
            'wantAttributeStatement': False
        }
    }
