public async Task <IActionResult> GetRepositoriesAsync() { var userId = User.FindFirstValue(ClaimConstants.ObjectId); var tenantId = User.FindFirstValue(ClaimConstants.TenantId); if (userId == default) { return(new BadRequestObjectResult(new { Error = "Object (User) id in token null or undefined" })); } if (tenantId == default) { return(new BadRequestObjectResult(new { Error = "Tenant id in token null or undefined" })); } var tokenResult = await _tokenProvider.GetAccessTokenAsync(tenantId : tenantId, userId : userId); if (tokenResult is NeedsConsentResult needsConsentResult) { return(new ObjectResult(new { authorize_url = needsConsentResult.AuthorizeUri, }) { StatusCode = (int)HttpStatusCode.PreconditionFailed, }); } else if (tokenResult is AccessTokenResult accessTokenResult) { var repositories = await _githubServiceClient.GetRepositoriesAsync(accessTokenResult.AccessToken); _logger.LogInformation("Repo count: {count}", repositories.Count); return(new JsonResult(repositories.ToList())); } _logger.LogWarning("Unknown access token return type: [{type}]", tokenResult.GetType()); return(new StatusCodeResult((int)HttpStatusCode.InternalServerError)); }
public override async Task <DialogTurnResult> BeginDialogAsync(DialogContext dc, object?options = null, CancellationToken cancellationToken = default) { dc = dc ?? throw new ArgumentNullException(nameof(dc)); if (options != null) { throw new ArgumentException($"{nameof(options)} cannot be defined for {nameof(AccountLinkingPrompt)}"); } // Initialize state var state = dc.ActiveDialog.State; state[ExpirationKey] = DateTimeOffset.UtcNow + _options.Timeout; var userId = dc.Context.Activity.From.AadObjectId; var tenantId = dc.Context.Activity.Conversation.TenantId; // Attempt to get the users token var tokenResult = await _oauthTokenProvider.GetAccessTokenAsync(tenantId : tenantId, userId : userId); if (tokenResult is NeedsConsentResult needsConsentResult) { var(codeChallenge, codeVerifier) = Pkce.GeneratePkceCodes(); var queryParams = HttpUtility.ParseQueryString(needsConsentResult.AuthorizeUri.Query); queryParams.Add("state", codeChallenge); // For bot we'll just use the codeChallenge as the 'state' queryParams.Add("code_challenge", codeChallenge); var loginConsentUri = new UriBuilder(needsConsentResult.AuthorizeUri) { Query = queryParams.ToString() }; // we can keep the code verifier out of the state[CodeVerifierKey] = codeVerifier; var activity = MessageFactory.Attachment(new Attachment { ContentType = SigninCard.ContentType, Content = new SigninCard { Text = "Please sign in", Buttons = new[] { new CardAction { Title = "Sign in", Type = ActionTypes.Signin, Value = loginConsentUri.ToString() }, }, }, }); var response = await dc.Context.SendActivityAsync(activity, cancellationToken : cancellationToken).ConfigureAwait(false); state[CardActivityKey] = response.Id; return(EndOfTurn); } else if (tokenResult is AccessTokenResult accessTokenResult) { return(await dc.EndDialogAsync(accessTokenResult, cancellationToken).ConfigureAwait(false)); } // Prompt user to login _logger.LogWarning("Unknown token result, ending turn"); return(EndOfTurn); }
protected override async Task <MessagingExtensionResponse> OnTeamsMessagingExtensionQueryAsync( ITurnContext <IInvokeActivity> turnContext, MessagingExtensionQuery query, CancellationToken cancellationToken) { var userId = turnContext.Activity.From.AadObjectId; var tenantId = turnContext.Activity.Conversation.TenantId; if (!string.IsNullOrEmpty(query.State)) { var authResponseObject = JsonSerializer.Deserialize <AuthResponse>(query.State); if (authResponseObject == default) { _logger.LogWarning("Invalid state object provided: {state}", query.State); throw new Exception("Invalid state format"); } _logger.LogInformation("Params:\nState: {state}\nCode: {code}", authResponseObject.State, authResponseObject.AccountLinkingState); var codeVerifier = _dataProtector.Unprotect(authResponseObject.State); await _oAuthTokenProvider.ClaimTokenAsync( accountLinkingToken : authResponseObject.AccountLinkingState, // these are inverted because codeVerifier : codeVerifier, tenantId : tenantId, userId : userId); } // Attempt to retrieve the github token var tokenResult = await _oAuthTokenProvider.GetAccessTokenAsync(tenantId : tenantId, userId : userId); if (tokenResult is NeedsConsentResult needsConsentResult) { _logger.LogInformation("Messaging Extension query with no GitHub token, sending login prompt"); var(codeChallenge, codeVerifier) = Pkce.GeneratePkceCodes(); var queryParams = HttpUtility.ParseQueryString(needsConsentResult.AuthorizeUri.Query); queryParams.Add("state", _dataProtector.Protect(codeVerifier)); queryParams.Add("code_challenge", codeChallenge); var loginConsentUri = new UriBuilder(needsConsentResult.AuthorizeUri) { Query = queryParams.ToString() }; return(new MessagingExtensionResponse { ComposeExtension = new MessagingExtensionResult { Type = "auth", SuggestedActions = new MessagingExtensionSuggestedAction { Actions = new List <CardAction> { new CardAction { Type = ActionTypes.OpenUrl, Title = "Please login to GitHub", Value = loginConsentUri.ToString() }, }, }, }, }); } else if (tokenResult is AccessTokenResult accessTokenResult) { var repos = await _gitHubServiceClient.GetRepositoriesAsync(accessTokenResult.AccessToken); return(new MessagingExtensionResponse { ComposeExtension = new MessagingExtensionResult { Type = "result", AttachmentLayout = "list", Attachments = repos.Select(r => new MessagingExtensionAttachment { ContentType = HeroCard.ContentType, Content = new HeroCard { Title = $"{r.Name} ({r.Stars})" }, Preview = new HeroCard { Title = $"{r.Name} ({r.Stars})" }.ToAttachment(), }).ToList(), }, }); } // There was an error return(new MessagingExtensionResponse { }); }