Skip to content

added ChannelProvider #451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
# regenerated.
# --------------------------------------------------------------------------
# pylint: disable=missing-docstring

from .government_constants import *
from .channel_provider import *
from .simple_channel_provider import *
from .microsoft_app_credentials import *
from .claims_identity import *
from .jwt_token_validation import *
from .credential_provider import *
from .channel_validation import *
from .emulator_validation import *
from .jwt_token_extractor import *
from .government_constants import *
from .authentication_constants import *
from .authentication_configuration import *
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from abc import ABC, abstractmethod


class ChannelProvider(ABC):
"""
ChannelProvider interface. This interface allows Bots to provide their own
implementation for the configuration parameters to connect to a Bot.
Framework channel service.
"""

@abstractmethod
async def get_channel_service(self) -> str:
raise NotImplementedError()

@abstractmethod
def is_government(self) -> bool:
raise NotImplementedError()

@abstractmethod
def is_public_azure(self) -> bool:
raise NotImplementedError()
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Licensed under the MIT License.

import asyncio
from typing import Union

import jwt

from .jwt_token_extractor import JwtTokenExtractor
Expand All @@ -10,6 +12,7 @@
from .credential_provider import CredentialProvider
from .claims_identity import ClaimsIdentity
from .government_constants import GovernmentConstants
from .channel_provider import ChannelProvider


class EmulatorValidation:
Expand Down Expand Up @@ -82,7 +85,7 @@ def is_token_from_emulator(auth_header: str) -> bool:
async def authenticate_emulator_token(
auth_header: str,
credentials: CredentialProvider,
channel_service: str,
channel_service_or_provider: Union[str, ChannelProvider],
channel_id: str,
) -> ClaimsIdentity:
""" Validate the incoming Auth Header
Expand All @@ -101,12 +104,14 @@ async def authenticate_emulator_token(
# pylint: disable=import-outside-toplevel
from .jwt_token_validation import JwtTokenValidation

if isinstance(channel_service_or_provider, ChannelProvider):
is_gov = channel_service_or_provider.is_government()
else:
is_gov = JwtTokenValidation.is_government(channel_service_or_provider)

open_id_metadata = (
GovernmentConstants.TO_BOT_FROM_EMULATOR_OPEN_ID_METADATA_URL
if (
channel_service is not None
and JwtTokenValidation.is_government(channel_service)
)
if is_gov
else Constants.TO_BOT_FROM_EMULATOR_OPEN_ID_METADATA_URL
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
# Licensed under the MIT License.

from abc import ABC
from typing import Union

from .authentication_configuration import AuthenticationConfiguration
from .authentication_constants import AuthenticationConstants
from .channel_validation import ChannelValidation
from .channel_provider import ChannelProvider
from .claims_identity import ClaimsIdentity
from .credential_provider import CredentialProvider
from .jwt_token_extractor import JwtTokenExtractor
Expand All @@ -26,9 +28,13 @@ async def authenticate_channel_token(
auth_header: str,
credentials: CredentialProvider,
channel_id: str,
channel_service: str,
channel_service_or_provider: Union[str, ChannelProvider],
auth_configuration: AuthenticationConfiguration = None,
) -> ClaimsIdentity:
channel_service = channel_service_or_provider
if isinstance(channel_service_or_provider, ChannelProvider):
channel_service = await channel_service_or_provider.get_channel_service()

endpoint = (
ChannelValidation.open_id_metadata_endpoint
if ChannelValidation.open_id_metadata_endpoint
Expand All @@ -55,11 +61,15 @@ async def authenticate_channel_token_with_service_url(
credentials: CredentialProvider,
service_url: str,
channel_id: str,
channel_service: str,
channel_service_or_provider: Union[str, ChannelProvider],
auth_configuration: AuthenticationConfiguration = None,
) -> ClaimsIdentity:
identity: ClaimsIdentity = await EnterpriseChannelValidation.authenticate_channel_token(
auth_header, credentials, channel_id, channel_service, auth_configuration
auth_header,
credentials,
channel_id,
channel_service_or_provider,
auth_configuration,
)

service_url_claim: str = identity.get_claim_value(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from typing import Dict, List
from typing import Dict, List, Union

from botbuilder.schema import Activity

Expand All @@ -15,6 +15,7 @@
from .government_constants import GovernmentConstants
from .government_channel_validation import GovernmentChannelValidation
from .skill_validation import SkillValidation
from .channel_provider import ChannelProvider


class JwtTokenValidation:
Expand All @@ -25,7 +26,7 @@ async def authenticate_request(
activity: Activity,
auth_header: str,
credentials: CredentialProvider,
channel_service: str = "",
channel_service_or_provider: Union[str, ChannelProvider] = "",
) -> ClaimsIdentity:
"""Authenticates the request and sets the service url in the set of trusted urls.
:param activity: The incoming Activity from the Bot Framework or the Emulator
Expand All @@ -51,7 +52,7 @@ async def authenticate_request(
claims_identity = await JwtTokenValidation.validate_auth_header(
auth_header,
credentials,
channel_service,
channel_service_or_provider,
activity.channel_id,
activity.service_url,
)
Expand All @@ -65,7 +66,7 @@ async def authenticate_request(
async def validate_auth_header(
auth_header: str,
credentials: CredentialProvider,
channel_service: str,
channel_service_or_provider: Union[str, ChannelProvider],
channel_id: str,
service_url: str = None,
auth_configuration: AuthenticationConfiguration = None,
Expand All @@ -78,18 +79,30 @@ async def get_claims() -> ClaimsIdentity:
return await SkillValidation.authenticate_channel_token(
auth_header,
credentials,
channel_service,
channel_service_or_provider,
channel_id,
auth_configuration,
)

if EmulatorValidation.is_token_from_emulator(auth_header):
return await EmulatorValidation.authenticate_emulator_token(
auth_header, credentials, channel_service, channel_id
auth_header, credentials, channel_service_or_provider, channel_id
)

is_public = (
not channel_service_or_provider
or isinstance(channel_service_or_provider, ChannelProvider)
and channel_service_or_provider.is_public_azure()
)
is_gov = (
isinstance(channel_service_or_provider, ChannelProvider)
and channel_service_or_provider.is_public_azure()
or isinstance(channel_service_or_provider, str)
and JwtTokenValidation.is_government(channel_service_or_provider)
)

# If the channel is Public Azure
if not channel_service:
if is_public:
if service_url:
return await ChannelValidation.authenticate_channel_token_with_service_url(
auth_header,
Expand All @@ -103,7 +116,7 @@ async def get_claims() -> ClaimsIdentity:
auth_header, credentials, channel_id, auth_configuration
)

if JwtTokenValidation.is_government(channel_service):
if is_gov:
if service_url:
return await GovernmentChannelValidation.authenticate_channel_token_with_service_url(
auth_header,
Expand All @@ -124,15 +137,15 @@ async def get_claims() -> ClaimsIdentity:
credentials,
service_url,
channel_id,
channel_service,
channel_service_or_provider,
auth_configuration,
)

return await EnterpriseChannelValidation.authenticate_channel_token(
auth_header,
credentials,
channel_id,
channel_service,
channel_service_or_provider,
auth_configuration,
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

from .channel_provider import ChannelProvider
from .government_constants import GovernmentConstants


class SimpleChannelProvider(ChannelProvider):
"""
ChannelProvider interface. This interface allows Bots to provide their own
implementation for the configuration parameters to connect to a Bot.
Framework channel service.
"""

def __init__(self, channel_service: str = None):
self.channel_service = channel_service

async def get_channel_service(self) -> str:
return self.channel_service

def is_government(self) -> bool:
return self.channel_service == GovernmentConstants.CHANNEL_SERVICE

def is_public_azure(self) -> bool:
return not self.channel_service
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT License.

from datetime import timedelta
from typing import Dict
from typing import Dict, Union

import jwt

Expand All @@ -13,6 +13,7 @@
from .government_constants import GovernmentConstants
from .verify_options import VerifyOptions
from .jwt_token_extractor import JwtTokenExtractor
from .channel_provider import ChannelProvider


class SkillValidation:
Expand Down Expand Up @@ -88,7 +89,7 @@ def is_skill_claim(claims: Dict[str, object]) -> bool:
async def authenticate_channel_token(
auth_header: str,
credentials: CredentialProvider,
channel_service: str,
channel_service_or_provider: Union[str, ChannelProvider],
channel_id: str,
auth_configuration: AuthenticationConfiguration,
) -> ClaimsIdentity:
Expand All @@ -99,9 +100,14 @@ async def authenticate_channel_token(

from .jwt_token_validation import JwtTokenValidation

if isinstance(channel_service_or_provider, ChannelProvider):
is_gov = channel_service_or_provider.is_government()
else:
is_gov = JwtTokenValidation.is_government(channel_service_or_provider)

open_id_metadata_url = (
GovernmentConstants.TO_BOT_FROM_EMULATOR_OPEN_ID_METADATA_URL
if channel_service and JwtTokenValidation.is_government(channel_service)
if is_gov
else AuthenticationConstants.TO_BOT_FROM_EMULATOR_OPEN_ID_METADATA_URL
)

Expand Down
Loading