7

The IDs to use for Bot Framework are in most cases easy to find, because you receive them in the "Activity" object that is sent to the bot when the user initiates contact.

However, I am trying to use the Create Conversation endpoint, which means I have to know the ID of the user and the bot.

https://learn.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-connector-api-reference?view=azure-bot-service-4.0#create-conversation

A simplified request (that works!) like this:

{
"bot": {
    "id": "28:4a4f500c-4897-4eaf-a364-c67942f41f6f"
},
"members":[{
    "id": "29:1DUjC5z4ttsBQa0fX2O7B0IDu30R_6SfPMhwj-E1BwWmvYzb_IElqJwzPDocwPxTS0j8clYeb8gZx67V8TuChbA"
}],
"tenantId": "c7392b95-d07b-4653-87a7-6c709f527c42"
}

I need to find the user id (member id) somehow, maybe through Graph API? Or maybe through the Bot Framework API? But how?

Additionally, I'd like to be able to also programmatically find the Bot ID because I would be deploying this bot to many tenants and it would simplify the configuration a lot. However, where do I find the Bot ID, even manually? It doesn't look like it is the App Id from Azure or the Object id.

(I understand the prefix of 28 and 29, so that is not related to my question)

UPDATE:

The key take aways from the accepted answer are the following:

The userId is unique to your bot ID and a particular user. You cannot reuse the userId between bots. The channelId is global.

This means I cannot hope to find the userId somewhere else and that is a very important piece of information.

When your app is installed in any particular context, you receive an onMembersAdded activity.

Apparently I can expect to receive a message in my bot even if the bot is just installed for a user. This would be my opportunity to find the userId.

When I try this out, I will confirm here whether that indeed happens in my scenario, which is a bot in a Personal Tab.

Niels Brinch
  • 3,033
  • 9
  • 48
  • 75
  • 1
    Hi could you please upvote if the answer given by @RajeeshMenoth solves your requirement. – Jagadeesh-MSFT Jun 22 '21 at 06:25
  • @Jagadeesh-MSFT I will. It is some very good and valuable information that certainly deserves an upvote, but it does not answer my question, as they assume I have an Activity object handy. This question is about making the bot initiate the conversation. – Niels Brinch Jun 22 '21 at 11:24
  • Hello @NielsBrinch, Was the answer provided by AnsumanBal-MT helpful? If it was then would you like to mark the answer accepted for the future reference of community members? – UserP Jun 28 '21 at 07:47
  • 1
    Prabhu, No. But Karthik correctly understood and answered the question and I marked his answer as accepted. – Niels Brinch Jul 01 '21 at 04:58

3 Answers3

5

For getting the bot id , you can find the Microsoft App ID from Azure portal of your bot configuration page which refers to the bot id of the bot service.

enter image description here

Your bot can access additional context about the team or chat, such as user profile.

A user ID can be found in the channel where your bot is connected . Your bot can query for the list of team members and their basic profiles. The basic profiles include Teams user IDs and Azure Active Directory (AAD) information such as name and object ID. enter image description here

  1. You can directly issue a GET request on /conversations/{teamId}/members/using the serviceUrl value as the endpoint.

The teamId can be found in the channeldata object of the activity payload that your bot receives in the following scenarios:

  • When a user messages or interacts with your bot in a team context.
  • When a new user or bot is added to a team. enter image description here

GET /v3/conversations/19:ja0cu120i1jod12j@skype.net/members

Response body
[{
    "id": "29:1GcS4EyB_oSI8A88XmWBN7NJFyMqe3QGnJdgLfFGkJnVelzRGos0bPbpsfJjcbAD22bmKc4GMbrY2g4JDrrA8vM06X1-cHHle4zOE6U4ttcc",
    "objectId": "9d3e08f9-a7ae-43aa-a4d3-de3f319a8a9c",
    "givenName": "Scott",
    "surname": "Mccall",
    "email": "Scott.Mccall@xyz.com",
    "userPrincipalName": "scall@xyz.com"
}, {
    "id": "29:1bSnHZ7Js2STWrgk6ScEErLk1Lp2zQuD5H2qQ960rtvstKp8tKLl-3r8b6DoW0QxZimuTxk_kupZ1DBMpvIQQUAZL-PNj0EORDvRZXy8kvWk",
    "objectId": "76b0b09f-d410-48fd-993e-84da521a597b",
    "givenName": "Allison",
    "surname": "Argent",
    "email": "Allison.Agrent@xyz.com",
    "userPrincipalName": "algent@xyz.com"
}]
  1. You can call GetConversationMembersAsync using Team.Id to return a list of user IDs.

// Fetch the members in the current conversation
var connector = new ConnectorClient(new Uri(context.Activity.ServiceUrl));
var teamId = context.Activity.GetChannelData<TeamsChannelData>().Team.Id;
var members = await connector.Conversations.GetConversationMembersAsync(teamId);

// Concatenate information about all members into a string
var sb = new StringBuilder();
foreach (var member in members.AsTeamsChannelAccounts())
{
    sb.AppendFormat(
        "GivenName = {0}, TeamsMemberId = {1}",
        member.Name, member.Id);

    sb.AppendLine();
}

// Post the member info back into the conversation
await context.PostAsync($"People in this conversation: {sb.ToString()}");
  1. node.js example

[...]
import * as builder from "botbuilder";
[...]

var teamId = session.message.sourceEvent.team.id;
connector.fetchMembers(
  (<builder.IChatConnectorAddress>session.message.address).serviceUrl,
  teamId,
  (err, result) => {
    if (err) {
      session.endDialog('There is some error');
    }
    else {
      session.endDialog('%s', JSON.stringify(result));
    }
  }
);

Using graph API or SDK (Note: Bot should be registered in app registration in active directory and the users also must be present in the Directory) :

  1. Get the Appid of the bot by using list and search :

GET https://graph.microsoft.com/v1.0/applications?$search="displayName:botname"&$count=true
ConsistencyLevel: eventual
  1. Get the list of users present in the active directory domain: (search by filtering the domain mail)
  • Using HTTP request

GET https://graph.microsoft.com/v1.0/users?$filter=endswith(mail,'a@xyz.com')&$orderby=userPrincipalName&$count=true
ConsistencyLevel: eventual
  • Using C#

GraphServiceClient graphClient = new GraphServiceClient( authProvider );

var users = await graphClient.Users
    .Request()
    .Header("ConsistencyLevel","eventual")
    .Filter("endswith(mail,'a@xyz.com')")
    .OrderBy("userPrincipalName")
    .GetAsync();

You will get a output like this :

 HTTP/1.1 200 OK 
Content-type: application/json 
{ 
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users", 
"@odata.count": 1, 
"value": [ 
{ 
"displayName": "Allison Argent", 
"givenName": "Allison", 
"jobTitle": "Senior Engineer", 
"mail": "algent@xyz.com", 
"userPrincipalName": "algent@xyz.com", 
"id": "e8b753b5-4117-464e-9a08-713e1ff266b3" 
} 
] 
}

Please refer to Integrate Bot with Azure Graph

Please refer a sample bot that uses Graph API.

Ansuman Bal
  • 9,705
  • 2
  • 10
  • 27
  • Regarding the Bot ID, although I am happy with your guideline, which I can definitely use, the question is if I can get it programmatically. I guess, in theory, I could get it by calling the Azure API, but I mean whether the bot itself can somehow find it. – Niels Brinch Jun 22 '21 at 11:16
  • Regarding the User ID, if I wait till the user interacts with the bot, then I can get the User ID from the Activity object as you describe. Then all is good. However, my question is if I can find the User ID before that time so I do not have to wait for the user to interact with the bot before I can send a message to the user. Maybe I want to send a message to all users on the tenant, including those who have not yet started using Teams. – Niels Brinch Jun 22 '21 at 11:18
  • As a side note, my bot is not in a channel but in a personal tab (but it doesn't really make a difference to the question so far) – Niels Brinch Jun 22 '21 at 11:19
  • 1
    are you referring tenant here as the Active directory Tenant ? if i understand correctly then you want to get all the users in that tenant / active directory through API and collect the id's and use it to send messages using bot ? – Ansuman Bal Jun 22 '21 at 13:32
  • for getting appid using Azure Graph API or SDK you can refer this : https://docs.microsoft.com/en-us/graph/api/application-list?view=graph-rest-1.0&tabs=http and the same way if the users are present in the active directory then you can get their id's but it will be of prefix 28 not 29 . (https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http) so in bot's case you can use the id collected from api but not sure if you can send messages to the users using the user object id that you have collected. You can integrate microsoft graph with bot to directly collect data . – Ansuman Bal Jun 22 '21 at 14:31
  • 1
    Yes, AnsumanBal, that is correct. I want to collect the IDs somehow. But the IDs that are needed to send to a user through a bot are not normal user ids. – Niels Brinch Jul 01 '21 at 04:51
3

While you're asking about bot id, I think your main question is really about proactive messaging. You're wanting bot id I think because of how some of the Microsoft docs recommend (really: "suggest") sending proactive messages. However, I prefer to use an approach that is much more simple, and requires only conversationid and serviceUrl. Please see here for a sample implementation (I've included both C# and Node versions).

In short, you get the Conversation Id and Service Url when the user installs the bot (personal scope, group chat, or Team channel). You can get it on any message the user sends actually, but getting it when they install the bot on activityUpdate is the best. You need to store Conversation Id and Service Url on your side, e.g. in a database, and then simply use them whenever you need to send the proactive message, as per the sample. Incidentally, I suggest also storing the timezone info from the activityUpdate, especially for users, because they may want messages sent at a particular time, depending on your app (8:00 for you might not be the same 8:00 for the user).

Update: Here's a video of an conference session I did which covered this topic - https://www.youtube.com/watch?v=mM7-fYdcJhw. The proactive stuff is about half-way through, but the early part might also be useful as background.

Hilton Giesenow
  • 9,809
  • 2
  • 10
  • 24
  • I dont have a ConversationId yet. That is what I would create if I had the UserId – Niels Brinch Jul 01 '21 at 04:55
  • Recall that the "Bot Framework" is used much more widely than just Teams. As a result, some things are applicable in one scenario but not in another - this is one of those. It's not -actually- possible to "Create" conversations in Teams in the same way. The conversation is "Created" by the user, when they install your bot, and thereafter there is only one single "Conversation" for all time between the user and the bot – Hilton Giesenow Jul 01 '21 at 08:04
  • As a result, you need to be -given- the conversation id. It comes through though any time the user interacts with the bot (e.g. any message the user ever sends), but it also comes the very first time the user -installs- your bot. Of course, this is the -best- time to get it because the you have it immediately as they install, and they don't even need to send a message. – Hilton Giesenow Jul 01 '21 at 08:05
  • 1
    See the updated answer - I found a video recording of a session I did earlier this year, covering the topic. – Hilton Giesenow Jul 01 '21 at 08:15
  • Understood. I didn't know that the bot would get the Activity when the bot is installed for a user by someone else, even if that user has never interacted with the bot. – Niels Brinch Jul 01 '21 at 08:25
  • yeah it's a bit of a learning curve, and made a little more challenging because the bot framework is "generic" - you need to learn the Teams-specific ins and outs – Hilton Giesenow Jul 01 '21 at 08:27
2

As per your requirement and I understood that you are trying to fetch member info from microsoft teams channel. You can easily find this out from the bot connector in the ms-team channel instead of using prefix 28 or 29. The Bot Connector REST API allows your bot to send and receive messages to channels and also the Bot State REST API allows a bot to store and retrieve state associated with users and conversations. So we can use the "Microsoft.Bot.Connector"to fetch the details of a user.

var connector = new ConnectorClient(new Uri(turnContext.Activity.ServiceUrl), "MicrosoftAppId", "MicrosoftAppPassword");
        var conversationId = turnContext.Activity.Conversation.Id;
        var channelInfo = turnContext.Activity.ChannelId;

        var userInfo = await connector.Conversations.GetConversationMembersAsync(conversationId);

The extension method "GetConversationMembersAsync" will fetch the member info from connector.

Output:

The "userInfo" object will return the following response. This details will contain important information like member id, objectId, tenantId,etc.

[{
"id": "29:15SDCCoTpDNJ_OiAdsOiMGAgg2S5HCRQvCt3ZVWbszpU5rSHkT95Zh2Tj1n-bhH4Sjc6zOBcuaSAUo-OtCm4ruD",
"name": "Rajeesh Menoth",
"aadObjectId": null,
"role": null,
"objectId": "bz341e75-60cf-8fdc-b490-04d6edd8a0f7",
"givenName": "Rajeesh",
"surname": "Raveendran",
"email": "Rajeesh.Menoth@menothsoft.com",
"userPrincipalName": "Rajeesh.Menoth@menothsoft.com",
"tenantId": "167f026d-8ffe-883f-5a11-9c2063481198",
"userRole": "user"
}]

Graph API:

If you don't have any ongoing conversation then, Graph API is the only way to get the user detail from application. BotID you can manually copy from bot channel registration service and user id you can pickup from graph API.

Please check this Microsoft Token Generator docs & Get user info using Graph API

Reference:

  1. Microsoft Connector Client
Rajeesh Menoth
  • 1,704
  • 3
  • 17
  • 33
  • Thank you. However, the reason why I want the User ID is so I can create a conversation with the user. So in this scenario I do not already have an ongoing conversation. So in this scenario, I would not yet have a turnContext or an Activity object. Using BotID and UserID I can create a conversation ID and then start sending messages to a user before they even start using the bot. – Niels Brinch Jun 22 '21 at 11:22
  • Side note: It is a bot in a personal tab and it appears in the "chat" area for the user in the left rail. It is not directly or indirectly related to a specific team or channel. – Niels Brinch Jun 22 '21 at 11:22
  • @NielsBrinch if you don't have any ongoing conversation then, Graph API is the only way to getting the user detail from application. BotID you can manually copy from bot channel registration service and user id you can pickup from graph API. I will update you the answer with graph api code. – Rajeesh Menoth Jun 22 '21 at 13:43
  • @NielsBrinch I don't think other than Graph API you can fetch User Id of a USER using AD authentication. – Rajeesh Menoth Jun 22 '21 at 13:58
  • I can get user ID from Graph API, but not the type of User ID that is required in order to send a message to a bot. – Niels Brinch Jul 01 '21 at 04:51