Reputation: 5
We have a Microsoft Teams message extension project which has a custom command for sign in:
"commands": [
{
"id": "SIGNIN",
"type": "action",
"title": "Sign In",
"description": "sign into our application",
"initialRun": false,
"fetchTask": true,
"context": [
"commandBox",
"compose",
"message"
],
"parameters": [
{
"name": "param",
"title": "param",
"description": ""
}
]
}
]
When clicked we open our application from Teams and prompt for login:
protected override async Task<MessagingExtensionActionResponse> OnTeamsMessagingExtensionFetchTaskAsync(ITurnContext<IInvokeActivity> turnContext, MessagingExtensionAction action, CancellationToken cancellationToken)
{
var state = action.State; // Check the state value
if (state != null)
{
var UserToken = JsonConvert.DeserializeObject<UserToken>(state);
}
// Handle different actions using switch.
switch (action.CommandId)
{
case "SIGNIN":
var output = new MessagingExtensionActionResponse
{
ComposeExtension = new MessagingExtensionResult
{
Type = "auth",
SuggestedActions = new MessagingExtensionSuggestedAction
{
Actions = new List<CardAction>
{
new CardAction
{
Type = ActionTypes.OpenUrl,
Value = "https://localhost:44302/Account/Login?loginfromteams=true",
Text = "Please sign in",
Title = "Sign in",
},
},
},
},
};
return await Task.FromResult(output);
}
}
Upon successful login to our application, we send a response back to Teams with a access token and refresh token:
<script>
document.onreadystatechange = function () {
microsoftTeams.app.initialize().then(function () {
microsoftTeams.authentication.notifySuccess(JSON.stringify({
accessToken: "@Model.AccessToken",
refreshToken: "@Model.RefreshToken",
}));
});
};
</script>
This is received by Teams in the action.State
parameter of the OnTeamsMessagingExtensionFetchTaskAsync
method shown above:
var state = action.State; // Check the state value
if (state != null)
{
var UserToken = JsonConvert.DeserializeObject<UserToken>(state);
UserToken.AccessToken // access token from our application available here
UserToken.RefreshToken // refresh token from our application available here
}
Now that we have a token, we want to store it in the users teams session so that they don't have to sign in to our application every time a call to our api is needed. We want this to persist in the application so that when the application is restarted the access token is still available for future api calls.
We can not see a clear way to store the token, either in a HTTP context or local storage. What is the recommended way forward?
Upvotes: 0
Views: 277
Reputation: 1039
After receiving the access token and refresh token from your application, you can use the UserToken property to store the access token in the user's Teams session. You can use the ITurnContext object to access the UserToken property.
var userToken = new UserToken
{
AccessToken = "<access token>",
RefreshToken = "<refresh token>"
};
await turnContext.TurnState.Get<IUserTokenProvider>
().SaveTokenAsync(turnContext, "<connection name>", "<user id>", userToken, cancellationToken);
To retrieve the access token for future API calls, you can use the UserToken property again.
var userToken = await turnContext.TurnState.Get<IUserTokenProvider>
().GetTokenAsync(turnContext, "<connection name>", "<user id>",
cancellationToken);
if (userToken != null)
{
var accessToken = userToken.AccessToken;
// Use the access token for API calls
}
Upvotes: 0