private async Task <AuthenticationResult> AcquireTokenForScopes(string[] scopes)
        {
            IConfidentialClientApplication cca = MsalAppBuilder.BuildConfidentialClientApplication();
            var account = await cca.GetAccountAsync(ClaimsPrincipal.Current.GetB2CMsalAccountIdentifier());

            return(await cca.AcquireTokenSilent(scopes, account).ExecuteAsync());
        }
Example #2
0
        private async Task <string> CallWebApiHelper(string apiUrl)
        {
            var app = MsalAppBuilder.BuildConfidentialClientApplication();

            var userAccount = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());

            if (userAccount == null)
            {
                // Dealing with guest users
                var accounts = await app.GetAccountsAsync();

                userAccount = accounts.Where(x => x.Username == ClaimsPrincipal.Current.GetLoginHint())
                              .FirstOrDefault();
            }

            var result = await app.AcquireTokenSilent(Globals.Scopes, userAccount)
                         .ExecuteAsync()
                         .ConfigureAwait(false);

            // Construct the query
            HttpClient         client  = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, apiUrl);

            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);

            // Ensure a successful response
            HttpResponseMessage response = await client.SendAsync(request);

            response.EnsureSuccessStatusCode();

            string json = await response.Content.ReadAsStringAsync();

            return(json);
        }
        public async Task SignOut()
        {
            await MsalAppBuilder.ClearUserTokenCache();

            HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
            Response.Redirect("/");
        }
Example #4
0
        public async Task SignOut()
        {
            await MsalAppBuilder.ClearUserTokenCache();

            // Send an OpenID Connect sign-out request.
            HttpContext.GetOwinContext().Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
        }
Example #5
0
        /*
         * Callback function when an authorization code is received
         */
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            try
            {
                /*
                 * The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
                 * At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
                 * but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
                 * receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
                 * This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
                 * Azure AD and has a full set of claims.
                 */
                IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));

                // Upon successful sign in, get & cache a token using MSAL
                AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(new HttpResponseMessage
                {
                    StatusCode   = HttpStatusCode.BadRequest,
                    ReasonPhrase = $"Unable to get authorization code {ex.Message}."
                });
            }
        }
Example #6
0
        // Get an access token. First tries to get the token from the token cache.
        public async Task <string> GetUserAccessTokenAsync()
        {
            string signedInUserID             = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication();

            try
            {
                string[]             scopes = ServiceHelper.Scopes.Split(new char[] { ' ' });
                AuthenticationResult result = await cc.AcquireTokenSilent(scopes, ClaimsPrincipal.Current.ToIAccount()).ExecuteAsync();

                return(result.AccessToken);
            }

            // Unable to retrieve the access token silently.
            catch (MsalUiRequiredException)
            {
                HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(
                    new AuthenticationProperties()
                {
                    RedirectUri = "/"
                },
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);

                throw new Exception(Resource.Error_AuthChallengeNeeded);
            }
        }
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            // Upon successful sign in, get the access token & cache it using MSAL
            IConfidentialClientApplication clientApp = await MsalAppBuilder.BuildConfidentialClientApplication();

            AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "Mail.Read" }, context.Code).ExecuteAsync();
        }
Example #8
0
        /// <summary>
        /// We obtain access token for Microsoft Graph with the scope "user.readbasic.all". Since this access token was obtained during the initial sign in process
        /// (OnAuthorizationCodeReceived) and cached, the user will not be prompted to sign in again.
        /// </summary>
        /// <returns></returns>
        private async Task <string> GetGraphAccessToken()
        {
            IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication();
            var userAccount = await cc.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());

            AuthenticationResult result = await cc.AcquireTokenSilent(new string[] { "user.readbasic.all" }, userAccount).ExecuteAsync();

            return(result.AccessToken);
        }
        /// <summary>
        /// We obtain access token for Microsoft Graph with the scope "group.read.all". Since this access token was not obtained during the initial sign in process
        /// (OnAuthorizationCodeReceived), the user will be prompted to consent again.
        /// </summary>
        /// <returns></returns>
        private async Task <string> GetGraphAccessToken(string[] scopes)
        {
            IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication();
            IAccount userAccount = await cc.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());

            Microsoft.Identity.Client.AuthenticationResult result = await cc.AcquireTokenSilent(scopes, userAccount).ExecuteAsync();

            return(result.AccessToken);
        }
        public async Task <ActionResult> Create(string description)
        {
            try
            {
                // Retrieve the token with the specified scopes
                string accessToken = null;
                var    scope       = new string[] { Globals.WriteTasksScope };

                IConfidentialClientApplication cca = MsalAppBuilder.BuildConfidentialClientApplication();
                var accounts = await cca.GetAccountsAsync();

                AuthenticationResult result = await cca.AcquireTokenSilent(scope, accounts.FirstOrDefault()).ExecuteAsync();

                accessToken = result.AccessToken;

                // Set the content
                var httpContent = new[] { new KeyValuePair <string, string>("Text", description) };

                // Create the request
                HttpClient         client  = new HttpClient();
                HttpContent        content = new FormUrlEncodedContent(httpContent);
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, apiEndpoint);
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                request.Content = content;
                HttpResponseMessage response = await client.SendAsync(request);

                // Handle the response
                switch (response.StatusCode)
                {
                case HttpStatusCode.OK:
                case HttpStatusCode.NoContent:
                case HttpStatusCode.Created:
                    return(new RedirectResult("/Tasks"));

                case HttpStatusCode.Unauthorized:
                    return(ErrorAction("Please sign in again. " + response.ReasonPhrase));

                default:
                    return(ErrorAction("Error. Status code = " + response.StatusCode));
                }
            }
            catch (MsalUiRequiredException ex)
            {
                /*
                 * If the tokens have expired or become invalid for any reason, ask the user to sign in again.
                 * Another cause of this exception is when you restart the app using InMemory cache.
                 * It will get wiped out while the user will be authenticated still because of their cookies, requiring the TokenCache to be initialized again
                 * through the sign in flow.
                 */
                return(new RedirectResult("/Account/SignUpSignIn?redirectUrl=/Tasks"));
            }
            catch (Exception ex)
            {
                return(ErrorAction("Error writing to list: " + ex.Message));
            }
        }
        private async Task OnAuthorizationCodeReceivedAsync(AuthorizationCodeReceivedNotification notification)
        {
            notification.HandleCodeRedemption();

            IConfidentialClientApplication confidentialClient = MsalAppBuilder
                                                                .BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));

            AuthenticationResult result = await confidentialClient
                                          .AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();

            notification.HandleCodeRedemption(null, result.IdToken);
        }
        /*
         *  Called when requesting to sign out
         */
        public async Task SignOut()
        {
            // To sign out the user, you should issue an OpenIDConnect sign out request.
            if (Request.IsAuthenticated)
            {
                await MsalAppBuilder.ClearUserTokenCache();

                IEnumerable <AuthenticationDescription> authTypes = HttpContext.GetOwinContext().Authentication.GetAuthenticationTypes();
                HttpContext.GetOwinContext().Authentication.SignOut(authTypes.Select(t => t.AuthenticationType).ToArray());
                Request.GetOwinContext().Authentication.GetAuthenticationTypes();
            }
        }
        // GET: Makes a call to the API and retrieves the list of tasks
        public async Task <ActionResult> Index()
        {
            try
            {
                // Retrieve the token with the specified scopes
                var scope = new string[] { Globals.ReadTasksScope };

                IConfidentialClientApplication cca = MsalAppBuilder.BuildConfidentialClientApplication();
                var accounts = await cca.GetAccountsAsync();

                AuthenticationResult result = await cca.AcquireTokenSilent(scope, accounts.FirstOrDefault()).ExecuteAsync();

                HttpClient         client  = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, apiEndpoint);

                // Add token to the Authorization header and make the request
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                HttpResponseMessage response = await client.SendAsync(request);

                // Handle the response
                switch (response.StatusCode)
                {
                case HttpStatusCode.OK:
                    string responseString = await response.Content.ReadAsStringAsync();

                    JArray tasks = JArray.Parse(responseString);
                    ViewBag.Tasks = tasks;
                    return(View());

                case HttpStatusCode.Unauthorized:
                    return(ErrorAction("Please sign in again. " + response.ReasonPhrase));

                default:
                    return(ErrorAction("Error. Status code = " + response.StatusCode + ": " + response.ReasonPhrase));
                }
            }
            catch (MsalUiRequiredException ex)
            {
                /*
                 * If the tokens have expired or become invalid for any reason, ask the user to sign in again.
                 * Another cause of this exception is when you restart the app using InMemory cache.
                 * It will get wiped out while the user will be authenticated still because of their cookies, requiring the TokenCache to be initialized again
                 * through the sign in flow.
                 */
                return(new RedirectResult("/Account/SignUpSignIn?redirectUrl=/Tasks"));
            }
            catch (Exception ex)
            {
                return(ErrorAction("Error reading to do list: " + ex.Message));
            }
        }
Example #14
0
        // Here we clear the token cache and end the session with the web app.
        public void SignOut()
        {
            if (Request.IsAuthenticated)
            {
                // Get the user's token cache and clear it.
                string userObjectId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
                MsalAppBuilder.ClearUserTokenCache();
            }

            // Send an OpenID Connect sign-out request.
            HttpContext.GetOwinContext().Authentication.SignOut(
                CookieAuthenticationDefaults.AuthenticationType);
            Response.Redirect("/");
        }
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            /*
             *           The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
             *           At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
             *           but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
             *           receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
             *           This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
             *           Azure AD and has a full set of claims.
             */
            IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(context.AuthenticationTicket.Identity));

            // Upon successful sign in, get & cache a token using MSAL
            AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(new[] { "user.readbasic.all" }, context.Code).ExecuteAsync();
        }
        public async Task <ActionResult> AccessToken()
        {
            // Before we render the send email screen, we use the incremental consent to obtain and cache the access token with the correct scopes
            IConfidentialClientApplication app    = MsalAppBuilder.BuildConfidentialClientApplication();
            AuthenticationResult           result = null;
            var accounts = await app.GetAccountsAsync();

            string[] scopes = { String.Format(" {0}/openid", AuthenticationConfig.Resource) };

            try
            {
                // try to get an already cached token
                result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync().ConfigureAwait(false);

                ViewBag.AccessToken = result.AccessToken;
                ViewBag.Environment = result.Account.Environment;

                // The 'preferred_username' claim can be used for showing the user's primary way of identifying themselves
                ViewBag.Username = result.Account.Username;
            }
            catch (MsalUiRequiredException ex)
            {
                // A MsalUiRequiredException happened on AcquireTokenSilentAsync.
                // This indicates you need to call AcquireTokenAsync to acquire a token
                Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");

                try
                {
                    // Build the auth code request Uri
                    string authReqUrl = await OAuth2RequestManager.GenerateAuthorizationRequestUrl(scopes, app, this.HttpContext, Url);

                    ViewBag.AuthorizationRequest = authReqUrl;
                    ViewBag.Relogin = "******";
                }
                catch (MsalException msalex)
                {
                    Response.Write($"Error Acquiring Token:{System.Environment.NewLine}{msalex}");
                }
            }
            catch (Exception ex)
            {
                Response.Write($"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}");
            }

            return(View());
        }
Example #17
0
        public async Task <ActionResult> Index()
        {
            IConfidentialClientApplication app    = MsalAppBuilder.BuildConfidentialClientApplication();
            AuthenticationResult           result = null;

            var accounts = await app.GetAccountsAsync();

            string[] scopes = { ProductApiConfiguration.ViewScope };

            try
            {
                // try to get token silently from the token cache
                result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync().ConfigureAwait(false);
            }
            catch (MsalUiRequiredException)
            {
                ViewBag.Relogin = "******";
                return(View());
            }
            catch (Exception ex)
            {
                ViewBag.Error = "An error has occurred. Details: " + ex.Message;
                return(View());
            }
            var products = new List <Product>();

            if (result != null)
            {
                // Use the token to read email
                HttpClient httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);
                HttpResponseMessage responseMessage = await httpClient.GetAsync(ProductApiConfiguration.GetProductsUrl);

                string productsResult = await responseMessage.Content.ReadAsStringAsync();

                if (productsResult.Length > 0)
                {
                    products = JsonConvert.DeserializeObject <List <Product> >(productsResult);
                }
                ViewBag.Message = productsResult;
            }


            return(View(products));
        }
Example #18
0
        /*
         * Callback function when an authorization code is received
         */
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            try
            {
                IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));

                // Upon successful sign in, get & cache a token using MSAL
                AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(B2C_Globals.Scopes, notification.Code).ExecuteAsync();
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(new HttpResponseMessage
                {
                    StatusCode   = HttpStatusCode.BadRequest,
                    ReasonPhrase = $"Unable to get authorization code {ex.Message}."
                });
            }
        }
Example #19
0
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            context.TokenEndpointRequest.Parameters.TryGetValue("code_verifier", out var codeVerifier);

            // Upon successful sign in, get the access token & cache it using MSAL
            IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
            AuthenticationResult           result    = await clientApp.AcquireTokenByAuthorizationCode(new[] { "Mail.Read User.Read" }, context.Code)
                                                       .WithSpaAuthorizationCode()         //Request an authcode for the front end
                                                       .WithPkceCodeVerifier(codeVerifier) // Code verifier for PKCE
                                                       .ExecuteAsync();

            HttpContext.Current.Session.Add("Spa_Auth_Code", result.SpaAuthCode);

            // This continues the authentication flow using the access token and id token retrieved by the clientApp object after
            // redeeming an access token using the access code.
            //
            // This is needed to ensure the middleware does not try and redeem the received access code a second time.
            context.HandleCodeRedemption(result.AccessToken, result.IdToken);
        }
        public async Task <ActionResult> SendMail()
        {
            // Before we render the send email screen, we use the incremental consent to obtain and cache the access token with the correct scopes
            IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();

            AuthenticationResult result = null;
            var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());

            string[] scopes = { "Mail.Send" };

            try
            {
                // try to get an already cached token
                result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
            }
            catch (MsalUiRequiredException ex)
            {
                // A MsalUiRequiredException happened on AcquireTokenSilentAsync.
                // This indicates you need to call AcquireTokenAsync to acquire a token
                Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");

                try
                {
                    // Build the auth code request Uri
                    string authReqUrl = await OAuth2RequestManager.GenerateAuthorizationRequestUrl(scopes, app, this.HttpContext, Url);

                    ViewBag.AuthorizationRequest = authReqUrl;
                    ViewBag.Relogin = "******";
                }
                catch (MsalException msalex)
                {
                    Response.Write($"Error Acquiring Token:{System.Environment.NewLine}{msalex}");
                }
            }
            catch (Exception ex)
            {
                Response.Write($"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}");
            }

            return(View());
        }
Example #21
0
        public ClientCredentialProvider GetAuthProvider()
        {
            string signedInUserID             = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication();

            try
            {
                var authProvider = new ClientCredentialProvider(cc);
                return(authProvider);
            }
            catch (Exception)
            {
                HttpContext.Current.Request.GetOwinContext().Authentication.Challenge(
                    new AuthenticationProperties()
                {
                    RedirectUri = "/"
                },
                    OpenIdConnectAuthenticationDefaults.AuthenticationType);

                throw new Exception(Resource.Error_AuthChallengeNeeded);
            }
        }
        public async Task <ActionResult> ReadMail()
        {
            IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication();

            AuthenticationResult result = null;
            var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());

            string[] scopes = { "Mail.Read" };

            try
            {
                // try to get token silently
                result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
            }
            catch (MsalUiRequiredException)
            {
                ViewBag.Relogin = "******";
                return(View());
            }
            catch (Exception eee)
            {
                ViewBag.Error = "An error has occurred. Details: " + eee.Message;
                return(View());
            }

            if (result != null)
            {
                // Use the token to read email
                HttpClient hc = new HttpClient();
                hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);
                HttpResponseMessage hrm = await hc.GetAsync("https://graph.microsoft.com/v1.0/me/messages");

                string rez = await hrm.Content.ReadAsStringAsync();

                ViewBag.Message = rez;
            }

            return(View());
        }
Example #23
0
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            String provisioningScope       = ConfigurationManager.AppSettings["SPPA:ProvisioningScope"];
            String provisioningEnvironment = ConfigurationManager.AppSettings["SPPA:ProvisioningEnvironment"];

            app.UseCookieAuthentication(new CookieAuthenticationOptions {
                CookiePath = $"/{provisioningScope}" ?? "/"
            });

            app.UseOAuth2CodeRedeemer(
                new OAuth2CodeRedeemerOptions
            {
                ClientId     = AuthenticationConfig.ClientId,
                ClientSecret = AuthenticationConfig.ClientSecret,
                RedirectUri  = AuthenticationConfig.RedirectUri
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                Authority             = AuthenticationConfig.Authority,
                ClientId              = AuthenticationConfig.ClientId,
                RedirectUri           = AuthenticationConfig.RedirectUri,
                PostLogoutRedirectUri = AuthenticationConfig.RedirectUri,
                Scope = $"{AuthenticationConfig.BasicSignInScopes} {AuthenticationConfig.GraphScopes}",
                TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    // instead of using the default validation (validating against a single issuer value, as we do in line of business apps),
                    // we inject our own multitenant validation logic
                    ValidateIssuer = false,
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    //SecurityTokenValidated = (context) =>
                    //{
                    //    return Task.FromResult(0);
                    //},
                    AuthorizationCodeReceived = async(context) =>
                    {
                        // Upon successful sign in, get the access token & cache it using MSAL
                        IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
                        AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(AuthenticationConfig.GetGraphScopes(), context.Code).ExecuteAsync();
                    },
                    AuthenticationFailed = (context) =>
                    {
                        var httpContext = (HttpContextBase)context.OwinContext.Environment["System.Web.HttpContextBase"];

                        var routeData = new RouteData();
                        routeData.Values["controller"] = "Home";
                        routeData.Values["action"]     = "Error";
                        routeData.Values["exception"]  = context.Exception;

                        IController errorController = DependencyResolver.Current.GetService <HomeController>();
                        var requestContext          = new RequestContext(httpContext, routeData);
                        errorController.Execute(requestContext);

                        // context.OwinContext.Response.Redirect("/Home/Error");
                        context.HandleResponse();     // Suppress the exception
                        //context.OwinContext.Response.Write(context.Exception.ToString());
                        return(Task.FromResult(0));
                    }
                }
            });
        }
Example #24
0
        public async Task <ActionResult> SendMail(string recipient, string subject, string body)
        {
            string messagetemplate = @"{{
  ""Message"": {{
    ""Subject"": ""{0}"",
    ""Body"": {{
                ""ContentType"": ""Text"",
      ""Content"": ""{1}""
    }},
    ""ToRecipients"": [
      {{
        ""EmailAddress"": {{
          ""Address"": ""{2}""
        }}
}}
    ],
    ""Attachments"": []
  }},
  ""SaveToSentItems"": ""false""
}}
";
            string message         = String.Format(messagetemplate, subject, body, recipient);

            HttpClient         client  = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/me/sendMail")
            {
                Content = new StringContent(message, Encoding.UTF8, "application/json")
            };


            IConfidentialClientApplication app    = MsalAppBuilder.BuildConfidentialClientApplication();
            AuthenticationResult           result = null;
            var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId());

            string[] scopes = { "Mail.Send" };

            try
            {
                // try to get an already cached token
                result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                /*
                 * When the user access this page (from the HTTP GET action result) we check if they have the scope "Mail.Send" and
                 * we handle the additional consent step in case it is needed. Then, we acquire an access token and MSAL cache it for us.
                 * So in this HTTP POST action result, we can always expect a token to be in cache. If they are not in the cache,
                 * it means that the user accessed this route via an unsual way.
                 */
                ViewBag.Error = "An error has occurred acquiring the token from cache. Details: " + ex.Message;
                return(View());
            }

            if (result != null)
            {
                // Use the token to send email

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                HttpResponseMessage response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    ViewBag.AuthorizationRequest = null;
                    return(View("MailSent"));
                }
            }


            return(View());
        }
Example #25
0
        public async Task <ActionResult> Create(string description)
        {
            try
            {
                ///
                /// Number validation occurs here, should be moved to external class
                ///
                if (System.Text.RegularExpressions.Regex.IsMatch(description, @"^[a-zA-Z]+$"))
                {
                    throw new WebException("Please provide a number");
                }
                if (String.IsNullOrEmpty(description))
                {
                    throw new WebException("Please provide a number");
                }
                if (description.Contains('.') && description.Split('.')[1].Length > 4)
                {
                    throw new WebException("The number can only have a precision of up to 4 decimal places");
                }
                if (description.Length >= 11)
                {
                    throw new WebException("number contains too many digits");
                }


                string accessToken = null;
                var    scope       = new string[] { Globals.WriteTasksScope };

                IConfidentialClientApplication cca = MsalAppBuilder.BuildConfidentialClientApplication();
                var accounts = await cca.GetAccountsAsync();

                AuthenticationResult result = await cca.AcquireTokenSilent(scope, accounts.FirstOrDefault()).ExecuteAsync();

                accessToken = result.AccessToken;

                // Set the content
                var httpContent = new[] { new KeyValuePair <string, string>("InputNumber", description) };

                // Create the request
                HttpClient         client  = new HttpClient();
                HttpContent        content = new FormUrlEncodedContent(httpContent);
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, apiEndpoint);
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                request.Content = content;
                HttpResponseMessage response = await client.SendAsync(request);

                // Handle the response
                switch (response.StatusCode)
                {
                case HttpStatusCode.OK:
                case HttpStatusCode.NoContent:
                case HttpStatusCode.Created:
                    return(new RedirectResult("/Numbers"));

                case HttpStatusCode.Unauthorized:
                    return(ErrorAction("Please sign in again. " + response.ReasonPhrase));

                default:
                    return(ErrorAction("Error. Status code = " + response.StatusCode));
                }
            }
            catch (MsalUiRequiredException ex)
            {
                /*
                 *  If the tokens have expired or become invalid for any reason, ask the user to sign in again.
                 *  Another cause of this exception is when you restart the app using InMemory cache.
                 *  It will get wiped out while the user will be authenticated still because of their cookies, requiring the TokenCache to be initialized again
                 *  through the sign in flow.
                 */
                return(new RedirectResult("/Account/SignUpSignIn?redirectUrl=/Numbers"));
            }
            catch (Exception ex)
            {
                return(ErrorAction("Error writing to list: " + ex.Message));
            }
        }
Example #26
0
        /*
         * Callback function when an authorization code is received
         */
        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            try
            {
                IConfidentialClientApplication confidentialClient = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(notification.AuthenticationTicket.Identity));

                // Upon successful sign in, get & cache a token using MSAL
                //AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(Globals.Scopes, notification.Code).ExecuteAsync();
                //string token = result.AccessToken;

                using (var client = new HttpClient())
                {
                    string tokenURL = "https://login.microsoftonline.com/rallycommunitas.onmicrosoft.com/oauth2/v2.0/token";

                    var requestContent = new FormUrlEncodedContent(new[]
                    {
                        new KeyValuePair <string, string>("grant_type", "client_credentials"),
                        new KeyValuePair <string, string>("client_id", Globals.RoleClientId),
                        new KeyValuePair <string, string>("scope", "https://graph.microsoft.com/.default"),
                        new KeyValuePair <string, string>("client_secret", Globals.RoleClientSecret)
                    });


                    var response1 = await client.PostAsync(tokenURL, requestContent);

                    var responseContent = await response1.Content.ReadAsStringAsync();

                    var    tokenObj    = JObject.Parse(responseContent);
                    JToken accessToke  = tokenObj.GetValue("access_token");
                    string accessToken = tokenObj.GetValue("access_token").Value <string>();



                    string requestUrl = $"https://graph.microsoft.com/v1.0/users/{notification.JwtSecurityToken.Subject}/memberOf?$select=displayName";

                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

                    HttpResponseMessage response = await client.SendAsync(request);

                    var responseString = await response.Content.ReadAsStringAsync();

                    var json = JObject.Parse(responseString);

                    foreach (var group in json["value"])
                    {
                        notification.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, group["displayName"].ToString(), System.Security.Claims.ClaimValueTypes.String, "Graph"));
                    }

                    //TODO: Handle paging.
                    // https://developer.microsoft.com/en-us/graph/docs/concepts/paging
                    // If the user is a member of more than 100 groups,
                    // you'll need to retrieve the next page of results.
                }


                //TODO - Approach 1
                // Get the Roles information from the JWT token. We can create a cutom attribute in the AD B2C directory and store the role information for the user. During the user sign-in we can include the custom attribute in the JWT token.

                //TODO - Approach 2
                //Get the user id from the JWT token, send the userid to AD B2C directory using Graph API to get the groups associated with the user. In this approach we need to create groups in the AD B2C Directory and assign groups to the user. here we can consider the group as Role.

                //TODO: Using any one of the approach, we can get the role information. Then, we can include the role claim details in the AuthenticationTicket.Identity

                //Example to add a role claim in the AuthenticationTicket.Identity
                //notification.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, "Administrator", System.Security.Claims.ClaimValueTypes.String, "Graph"));
            }
            catch (Exception ex)
            {
                throw new HttpResponseException(new HttpResponseMessage
                {
                    StatusCode   = HttpStatusCode.BadRequest,
                    ReasonPhrase = $"Unable to get authorization code {ex.Message}."
                });
            }
        }
Example #27
0
 private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
 {
     // Upon successful sign in, get the access token & cache it using MSAL
     IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication(new ClaimsPrincipal(context.AuthenticationTicket.Identity));
     AuthenticationResult           result    = await clientApp.AcquireTokenByAuthorizationCode(new[] { String.Format(" {0}/openid", AuthenticationConfig.Resource) }, context.Code).ExecuteAsync();
 }
        /// <summary>
        /// Called by Azure AD. Here we end the user's session, but don't redirect to AAD for sign out.
        /// </summary>
        public async Task EndSession()
        {
            await MsalAppBuilder.ClearUserTokenCache();

            HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
        }