BotBuilder Authentication Multitenant - azure

I want to create Microsoft BotBuilder following this tutorial. But it seems SO complicated compared to v3.(BTW: starting a tutorial with 3 authentications that cover 75% of the article is not a good sign)
So I follow the EchoBot sample (I chose MultiTenant because my server is outside AND it seems the most covered):
const credentialsFactory = new BotBuilder.ConfigurationServiceClientCredentialFactory({
MicrosoftAppId: '***',
MicrosoftAppPassword: '***',
MicrosoftAppType: 'MultiTenant',
});
const botFrameworkAuthentication = BotBuilder.createBotFrameworkAuthenticationFromConfiguration(null, credentialsFactory);
const onTurnErrorHandler = async (context, error) => { /* for errors */ }
const adapter = new BotBuilder.CloudAdapter(botFrameworkAuthentication);
adapter.onTurnError = onTurnErrorHandler;
Questions:
How do I test everything is working ? isValidAppId() and isAuthenticationDisabled() are the only available method and seems OK.
How do I get MicrosoftAppPassword ? According to the documentation I have to click manage, then create a value/secret pair. Should I use value ? or secret ? Why none is named password ? Anyway none works ...
To test if it works, I follow the sample:
setup an HTTP POST Endpoint (with Node-RED)
declare the endpoint in Azure Portal Bot Configuration
go to webchat to test
I correctly receive the Messages then try to do some authentication/parisng (I assume) :
await adapter.process(msg.req, msg.res, (context) => {
/* do some stuff */
});
But it fails with a very explicit error :
Error: 1 validation issue(s)
Issue #0: custom_error at [[root]]
Response
I think, the errors is related to an authentication issue, since I don't understand what/how to set the password. I guess I have to go through this CloudAdapter in order to get a parsed context and be able to send messages.
EDIT 07/05/2022:
I use the AppId from here :
I click "Manage" but where is the AppPassword ?
EDIT 12/05/2022:
Using cURL I manage to validate the appID and appPassword (the value (hidden by stars) of the secret).
BotBuilder is mixing the Communication Stack (HTTP / WebSocket) and the Logic stack (Turn Conversation). I think it's a bad habbit but I manage a workaround:
I use a BotFrameworkAdapter instead of CloudAdpater
I call adapter.processActivity() instead of adapter.process()
The adapter still want to end() the request and set deprecated values but it works in Node-RED. The context handle all the requirement to call sendActivity() anywhere multiple times.

To answer second question in your case, kindly go through the link :https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration?view=azure-bot-service-4.0&tabs=multitenant
To answer the first question in your case, kindly check disabling and enabling the authentication to test the app: https://learn.microsoft.com/en-us/azure/bot-service/bot-service-troubleshoot-authentication-problems?view=azure-bot-service-4.0&tabs=csharp

As far as getting the password goes, when you create a new Multi Tenant Azure Bot resource, the app password goes into the Azure Key Vault created alongside it. The AppId and AppPassword are randomly generated by Azure. You can get them from the key vault in the Azure portal in the correct resource group.
If you want to create a resource manually using the CLI and define your own password, you can use this docs page for deploying a bot. Make sure you select the correct tabs. I have pre-selected C# and Multi Tenant in a new resource group for the above link.
Single Tenant is for limiting your bot's connections to Azure resources within the same tenant, and a User Assigned Managed Identity is if you want to make use of an Azure Managed Identity across the bot's resources instead of having a password for each resource.
You should be able to simply add the AppId and AppPassword to the echo bot sample and deploy it.

Related

Azure Key Vault: The user, group, or app does not have secrets set permission on key vault

I am creating a script using Azure CLI that will automatically generate an App Registration (service principal), and then use that App Registration to create a secret that will be stored in Azure Key Vault.
However, I am getting the following error:
The user, group or application 'appid=04b07795-8ddb-461a-bbee-02f9e1bf7b46;oid=0ec2b0e8-daeb-46a8-b627-0d4f61f87157;numgroups=134;iss=https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/' does not have secrets set permission on key vault 'asakeyabcfelaqpgsfnxcy;location=eastus'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287
Can anyone provide guidance on what this ID is and how to resolve this error? This is not my App Registration Object ID or App ID.
I think there're 2 points you're now concerning, one is you failed to add secret, another is the app id in the error message is not the one you registered.
I think you've followed the document to execute the cli command, so I just want to explain the second point. Pls allow me show you a code sample for a better explanation.
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
public async Task<IActionResult> PrivacyAsync()
{
var kvUri = "https://your_vault_name.vault.azure.net/";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
_ = await client.SetSecretAsync("test0311", "hello");
return View();
}
When we want to add key vault secret to azure, we need to provide a credential so that our operations are authenticated. This is the DefaultAzureCredential() here, and it has several sources to get the authentication like screenshot below.
That means if someone sets the environment variables for authentication, then it will cover the information you entered when executing cli command, this may usually cause the issue that the app is different from what you set. I think you may follow this document to check all your configurations and try again, or you can directly add environment variables with the app you registered on your computer.
By the way, pls don't forget to add access policy in azure portal for the azure ad app you registered.

MS Identity Azure app registered but sends unauthorized_client in implicit flow

I have registered an app in Azure for Microsoft Identity platform. I configured it to allow MS Accounts (e.g. outlook.com) and have basically done everything in a few of the quickstarts online here and here (except for "add credentials to your web app"). I have also checked the boxes that enable implicit flow.
I redirect my React application to the URL to sign in (using implicit flow), I get to enter my username but then I see
unauthorized_client: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908
Like I mentioned above, I've gone through several quick starts and read about implicit flow here and followed their examples for my code.
I also tried just deleting the app registration and starting over. No luck.
JS Code attempting to implement Implicit Flow
JS code that redirects the browser to a Url that looks like Microsoft's first example on their implicit flow page
goSignIn() {
const tenant = 'common'; // (for us with MS accounts)
const clientId = '*****';
const redir = encodeURIComponent('http://localhost:3000/signin');
const nonce = Math.round(Math.random() * 10000, 0);
const uriTemplate = 'https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?client_id={clientId}&response_type=id_token+token&redirect_uri={redirect}&scope=openid&response_mode=fragment&state={state}&nonce={nonce}';
const filledTemplate = uriTemplate
.replace('{tenant}', tenant)
.replace('{clientId', clientId)
.replace('{redirect}', redir)
.replace('{nonce}', nonce)
.replace('{state}', nonce);
console.log(filledTemplate);
window.location = filledTemplate;
}
App Configuration in Azure:
Azure -> Identity -> App Registrations -> MyApp -> Authentication
Redirect Uri: http://localhost:3000/signin (React app runs on 3000 and I have a route configured for /signin)
Not using any suggested Redirects.
Checked Implicit checkboxes for ID Token and Access Token
Live SDK support enabled
Supported account types is set to "Accounts in any organizational directory and personal Microsoft accounts (e.g. Skype, Xbox, Outlook.com)"
Azure -> Identity -> App Registrations -> MyApp -> API Permissions
MS Graph
User.Read
Email
Profile
openid
From the docs I read, I thought I had done enough to the id token. I'm not sure what tweak must be made in order to get it to work.
I experienced an issue like this one. The mistake I made has to do with the App ID: when you create the client secret the Azure UI will present the secret and the secret ID. This secret ID is not the one to use in your app's configuration. Rather, you need the Application ID found on the Overview page.
I imagine that there are many configuration problems which can produce this error message. In general: pay close attention to the App ID, if the error is that the app is not found.
It seems that you have done enough to get the token. I have tested this on my side, it works well. Here I provide you with my screenshot for you to check again.
Also, here is my working request url, you can login with your msa to have a test.
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=5fd66168-7ba3-4bbc-a155-bff662eed9f7
&response_type=id_token+token
&redirect_uri=http://localhost:3000/signin
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910

SaaS App with AzureADB2C: User Flows for Client SSO?

We have a SaaS web app and our clients are requiring SSO authentication for each of them. We are using AzureADB2C and it works great, but now are looking at adding SSO.
I put in the SSO setup into the B2C tenet and it works great, but really messed up our login screen with a "MyCompanySSO" button to log in with, on our customer-facing login screen.
So now my idea is to have a separate user flow that handles each SSO setup. Starting with us. We'd go to MyCompany.OurSaaSApp.us and that'd forward them directly to the user flow endpoint and prompt them to login with their SSO account (AzureAD).
This all seems to try to work, but I'm getting these errors within the AzureADB2C middleware:
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Warning: .AspNetCore.Correlation. state property not found.
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler:Information: Error from RemoteAuthentication: Correlation failed..
Then I get pumped out onto a error page and the login fails.
So 2 things...
1.) Am I going in the right direction knowing what we're wanting to accomplish
2.) What do we need to do to resolve this?
Thanks everyone for the help, it's been greatly appreciated.
(note:)
Just to reiterate. The SSO works properly when the custom identity provider is attached to the existing SignUpOrIn UserFlow I have configured in the app. I'm only getting this error when I try to use another UserFlow that I want to use specifically for this SSO.
I'm not sure about that specific error, although "state" parameter is a parameter that your app sends in the request that will be returned in the token for correlation purposes.
Using and different policy for each federation sounds like the right approach, but if you are doing from a single instance of your app, you'll need to modify the OIDC protocol message with the correct authority (ie policy) on redirect.
In your OIDC middleware configuration, set up a handler for the RedirectToIdentityProvider notification. Then handle it with something like:
private Task OnRedirectToIdentityProvider(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
//var policy = notification.OwinContext.Get<string>("Policy");
var tenantSegment = notification.Request.Path.Value.Split(new char [] { '/'}, StringSplitOptions.RemoveEmptyEntries)[0];
if (!string.IsNullOrEmpty(tenantSegment) && !tenantSegment.Equals(DefaultPolicy))
{
notification.ProtocolMessage.IssuerAddress = notification.ProtocolMessage.IssuerAddress.ToLower().Replace(DefaultPolicy.ToLower(), $"B2C_1A_{tenantSegment.ToLower()}_SignUpSignInPolicy");
}
return Task.FromResult(0);
}
If you need to inject anything else tenant-related, that would be the place to do it.

High Trust S2S Provider Hosted App with "App + User" Policy

I am relatively new to sharepoint app development.
Trying to create a on premises, High Trust provider hosted app with App + User Policy. I have followed below document to create a demo.
https://msdn.microsoft.com/library/office/fp179901(v=office.15)
http://blogs.msdn.com/b/russmax/archive/2014/06/23/part-1-intro-to-provider-hosted-apps-setup-the-infrastructure.aspx
I am facing few issue and I have some question to clarify, if anybody can help.
1) When I inspect my request in dev tools, it give me below form data.
SPAppToken:
SPSiteUrl:
SPSiteTitle:Home
SPSiteLogoUrl:
SPSiteLanguage:en-US
SPSiteCulture:en-US
SPRedirectMessage:EndpointAuthorityMatches
SPErrorCorrelationId:f069e89c-a0cd-20ce-a1c0-7db95db0334b
now when i inspect log with above corelation id, i am finding below errors.
-- Error when get token for app i:0i.t|ms.sp.ext|ab8ff461-bc75-4516-b475-b666ac47eec0#802f23e1-6e11-45d1-909c-07a7b0ab0ce2,
exception: Microsoft.SharePoint.SPException: The Azure Access Control
service is unavailable.
-- App token requested from appredirect.aspx for site: 92bfe5c4-7255-4b09-a89a-07e0e2b03622 but there was an error in
generating it. This may be a case when we do not need a token or when
the app principal was not properly set up.
-- Getting Error Message for Exception Microsoft.SharePoint.SPException: The Azure Access Control service is
unavailable.
a) I belive in high-trust app it shouldn't look for Azure ACS.
Is this error because of some incorrect configuration?
b) SPAppToken is null here. Is it null always in case of hig trust app?
2) Say I am logged into sharepoint with User A and trying to launch sharepoint app.
Within app code I want to get identity of logged in user(which is A). From below code i found that Request.LogonUserIdentity gives me identity of user A. But how can we sure that request is came from sharepoint only. I can copy the same app URL and paste in browser window and login with window credential and get the same result. So question is how can I verify if its legitimate request came from sharepoint only and no one is faking request.
ALos, when I inspect request in dev tools, its passing Authorization key in request header. What is use of this?
using (var clientContext = TokenHelper.GetS2SClientContextWithWindowsIdentity(hostWeb, Request.LogonUserIdentity)) { clientContext.Load(clientContext.Web, web => web.Title); clientContext.ExecuteQuery(); Response.Write(clientContext.Web.Title); }
3) Also what happens if my app doesnt support windows authentication and only support FBA, is there any way to get user identity in this case?
Any help would be much appreciated.
Thanks
For issue #1: It looks to me that the step # 9 (Configure authentication settings) in this section (from the first MSDN article you have referred) was missed, i.e., 'ACS Control service' was selected instead of 'Use a Certificate' option.
For issue #2: There are helper methods in TokenHelper.cs to validate the AccessToken from the HttpRequest, which identifies the validity of the request.

Azure Graph API: authorize application on multiple tenants

I am trying to create an application to browse my contacts directory on Exchange.
I have set up everything and I am able request the authorization from my app.
I can present the modal view, enter the login information, retrieve the token, but when I try to authorize the app with the same account I have created it I get this message:
The client <my app id> and resource <my app URI> identify the same application.
If I try to authorize another account, I receive this message instead:
User account <an email> from external identity provider <a url> is not
supported for application <my app id>
If I try to login on the Graph Explorer Console or on the Office 365 OAuth Sandbox, they work fine with the second address, but not with the first one.
I am really confuse. I feel like I have mess up some configuration option, but I don't really understand which one.
Regarding #1, please do not pass App ID of your application for resource querystring parameter when authenticating against your tenant URL. I ran into the exact same problem.
Then I ran WebApp-MultiTenant-OpenIdConnect-DotNet from Github and noted down the sign-in URL it created and I used the following:
var signInUrl = String.Format(
"https://login.windows.net/{0}/oauth2/authorize?response_mode=form_post&response_type=code+id_token&scope=openid+profile&client_id={1}&resource={2}&redirect_uri={3}&state={4}&nonce={5}",
Uri.EscapeDataString(tenantId),
Uri.EscapeDataString(clientId),
Uri.EscapeDataString("https://graph.windows.net"),
Uri.EscapeDataString(redirectUri),
Uri.EscapeDataString(state),
string.Format("{0}{1}", DateTime.UtcNow.Ticks, Guid.NewGuid().Stringify())
);
Basically I used https://graph.windows.net instead of App ID and magically things started to work :).
Another thing you could try (and I have not tried it) is authenticating against common endpoint https://login.windows.net/common/oauth2/authorize and provide your App ID for the resource querystring.

Resources