I have the same problem with the quick start sample project.
Teams Bot OAuthPrompt Not returning Tokenresponse for a couple of company members
I have made and implemented a Teams bot for my company that is connected to a ASP.NET program on Azure but I am having some problems using the OAuthPrompt
.
To give you some context and application insight: The endpoint is a BotController that allows Anonymous requests on /api/messages
, this then uses the IBotFrameworkHttpAdapter
and IBot
to handle the request. My adapter is using base.Use(new TeamsSSOTokenExchangeMiddleware)
to get SSO to work. In the IBot
I override the method OnMessageActivityAsync
to process incomming request. I first check if the user is trying to log out (mainly testing debugging purposes) and if not logout it tries to get the userToken, if this returns a succes, I will process the message which is working. If tokenResponse == null
, I start a dialog for the authentication. In here I register an OAuthPrompt
and a WaterfallDialog
to process the authentication.
The services:
services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();
services.AddTransient<MainDialog>();
services.AddTransient<IBot, TeamsBot<MainDialog>>();
and the main dialog:
public MainDialog(IConfiguration configuration, IMemoryCache memoryCache, ITeamsService teamsService)
{
_memoryCache = memoryCache;
_teamsService = teamsService;
_configuration = configuration;
AddDialog(new OAuthPrompt(
nameof(OAuthPrompt),
new OAuthPromptSettings
{
ConnectionName = configuration["ConnectionName"] ?? throw new ArgumentException("ConnectionName"),
Text = "Please Sign In",
Title = "Sign In",
Timeout = 300000, // User has 5 minutes to login (1000 * 60 * 5)
EndOnInvalidMessage = true
}));
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
{
PromptStepAsync,
LoginStepAsync,
}));
// The initial child Dialog to run.
InitialDialogId = nameof(WaterfallDialog);
}
private async Task<DialogTurnResult> PromptStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
Log.Information("PromptStepAsync() called.");
return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
}
private async Task<DialogTurnResult> LoginStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
// Get the token from the previous step. Note that we could also have gotten the
// token directly from the prompt itself. There is an example of this in the next method.
var tokenResponse = (TokenResponse)stepContext.Result;
String? question;
_memoryCache.TryGetValue(stepContext.Context.Activity.From.Id, out question);
if (tokenResponse == null)
{
Console.WriteLine($"LoginStepAsync: tokenResponse is null, question={question ?? "question is leeg"}");
} else
{
Console.WriteLine($"LoginStepAsync: question={question ?? "question is leeg"}, fromId: {stepContext.Context.Activity.From.Id}, tokenResponse: {tokenResponse.ConnectionName} / {tokenResponse.ChannelId} / {tokenResponse.Expiration}, hasToken: {tokenResponse.Token != null}");
Console.WriteLine($"LoginStepAsync: fromId={stepContext.Context.Activity.From.Id}");
Console.WriteLine($"LoginStepAsync: tokenResponse.ConnectionName={tokenResponse.ConnectionName}");
Console.WriteLine($"LoginStepAsync: tokenResponse.ChannelId={tokenResponse.ChannelId}");
Console.WriteLine($"LoginStepAsync: tokenResponse.Expiration={tokenResponse.Expiration}");
Console.WriteLine($"LoginStepAsync: hasToken={tokenResponse.Token != null}");
Console.WriteLine($"LoginStepAsync: tokenResponse.Properties={tokenResponse.Properties?.ToString() ?? "null"}");
}
if (tokenResponse?.Token != null && question != null)
{
await _teamsService.ProcessTeamsMessageAsync(stepContext.Context, question, tokenResponse.Token, cancellationToken);
}
else
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text("Stuur je vraag nogmaals aub."), cancellationToken);
return await stepContext.BeginDialogAsync(nameof(OAuthPrompt), null, cancellationToken);
}
return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
var userTokenClient = turnContext.TurnState.Get<UserTokenClient>();
if (turnContext.Activity.Text.Equals("logout"))
{
await userTokenClient.SignOutUserAsync(turnContext.Activity.From.Id, _connectionName, turnContext.Activity.ChannelId, cancellationToken: cancellationToken);
await turnContext.SendActivityAsync(MessageFactory.Text("You have been signed out."), cancellationToken);
return;
}
var tokenResponse = await userTokenClient.GetUserTokenAsync(turnContext.Activity.From.Id, _connectionName, turnContext.Activity.ChannelId, null, cancellationToken).ConfigureAwait(false);
if (tokenResponse == null)
{
_memoryCache.Set(turnContext.Activity.From.Id, turnContext.Activity.Text, TimeSpan.FromMinutes(5));
await _dialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
return;
}
await _teamsService.ProcessTeamsMessageAsync(turnContext, turnContext.Activity.Text, tokenResponse.Token, cancellationToken);
}
As you can see in the image, the user tries to logout, and when sending the next message it fails, when trying to send it again it keeps giving the message Stuur je vraag nogmaals aub.
When trying this as another user, everything works fine and the message to resend the question never shows. I checked Entra ID and there are no specific groups that are different. When I send the person a direct connection link (the one provided in the azure bot configuration), it instantly shows the token without login.
[![enter image description here][1]][1]
Is there anything I am missing or doing wrong with the dialog stuff? Please let me know if you need any extra information!
EDIT
As someone else also pointed out, they also get this problem with the quick start sample project. Someone from Microsoft should really look into this. Where do I file a bug report? [1]: https://i.stack.imgur.com/vFuaz.png