예제 #1
0
        /// <summary>
        /// Logs the user into Office 365.
        /// </summary>
        /// <param name="authState">The login or logout status of the user.</param>
        /// <returns>A redirect to the Office 365 login page.</returns>
        public async Task <ActionResult> Login(string authState)
        {
            if (string.IsNullOrEmpty(Settings.AzureADClientId) || string.IsNullOrEmpty(Settings.AzureADClientSecret))
            {
                ViewBag.Message = "Please set your client ID and client secret in the Web.config file";
                return(View());
            }

            ConfidentialClientApplicationBuilder clientBuilder = ConfidentialClientApplicationBuilder.Create(Settings.AzureADClientId);
            ConfidentialClientApplication        clientApp     = (ConfidentialClientApplication)clientBuilder.Build();

            // Generate the parameterized URL for Azure login.
            string[] graphScopes = { "Files.Read.All", "User.Read" };
            var      urlBuilder  = clientApp.GetAuthorizationRequestUrl(graphScopes);

            urlBuilder.WithRedirectUri(loginRedirectUri.ToString());
            urlBuilder.WithAuthority(Settings.AzureADAuthority);
            urlBuilder.WithExtraQueryParameters("state=" + authState);
            var authUrl = await urlBuilder.ExecuteAsync(System.Threading.CancellationToken.None);

            // Redirect the browser to the login page, then come back to the Authorize method below.
            return(Redirect(authUrl.ToString()));
        }
예제 #2
0
        public async Task ClientCreds_NonExpired_NeedsRefresh_AADUnavailableResponse_Async()
        {
            // Arrange
            using (MockHttpAndServiceBundle harness = base.CreateTestHarness())
            {
                Trace.WriteLine("1. Setup an app with a token cache with one AT");
                ConfidentialClientApplication app = SetupCca(harness);

                Trace.WriteLine("2. Configure AT so that it shows it needs to be refreshed");
                UpdateATWithRefreshOn(app.AppTokenCacheInternal.Accessor, DateTime.UtcNow - TimeSpan.FromMinutes(1));
                TokenCacheAccessRecorder cacheAccess = app.AppTokenCache.RecordAccess();

                Trace.WriteLine("3. Configure AAD to respond with an error");
                harness.HttpManager.AddAllMocks(TokenResponseType.Invalid_AADUnavailable503);
                harness.HttpManager.AddTokenResponse(TokenResponseType.Invalid_AADUnavailable503);

                // Act
                AuthenticationResult result = await app.AcquireTokenForClient(TestConstants.s_scope)
                                              .ExecuteAsync()
                                              .ConfigureAwait(false);

                // Assert
                Assert.IsNotNull(result, "ClientCreds should still succeeds even though AAD is unavaible");
                Assert.AreEqual(0, harness.HttpManager.QueueSize);
                cacheAccess.AssertAccessCounts(1, 0); // the refresh failed, no new data is written to the cache

                // Now let AAD respond with tokens
                harness.HttpManager.AddTokenResponse(TokenResponseType.Valid);

                result = await app.AcquireTokenForClient(TestConstants.s_scope)
                         .ExecuteAsync()
                         .ConfigureAwait(false);

                Assert.IsNotNull(result);
                cacheAccess.AssertAccessCounts(2, 1); // new tokens written to cache
            }
        }
예제 #3
0
        public async Task <ActionResult> SendMail()
        {
            // try to get token silently

            string     signedInUserID         = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            TokenCache userTokenCache         = new MSALSessionCache(signedInUserID, this.HttpContext).GetMsalCacheInstance();
            ConfidentialClientApplication cca = new ConfidentialClientApplication(clientId, redirectUri, new ClientCredential(appKey), userTokenCache, null);
            var accounts = await cca.GetAccountsAsync();

            if (accounts.Any())
            {
                string[] scopes = { "Mail.Read" };
                try
                {
                    AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes, accounts.First());
                }
                catch (MsalUiRequiredException)
                {
                    try
                    {
                        // when failing, manufacture the URL and assign it

                        string authReqUrl = await Calendar_OneDrive_Mail_Graph.Utils.OAuth2RequestManager.GenerateAuthorizationRequestUrl(scopes, cca, this.HttpContext, Url);

                        ViewBag.AuthorizationRequest = authReqUrl;
                    }
                    catch (Exception ex)
                    {
                        Response.Write(ex.Message);
                    }
                }
            }
            else
            {
            }
            return(View());
        }
예제 #4
0
        public async Task<ActionResult> Delete(string id)
        {
            try
            {
                // Retrieve the token with the specified scopes
                var scope = new string[] { Startup.WriteTasksScope };
                string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
                TokenCache userTokenCache = new MSALSessionCache(signedInUserID, this.HttpContext).GetMsalCacheInstance();
                ConfidentialClientApplication cca = new ConfidentialClientApplication(Startup.ClientId, Startup.Authority, Startup.RedirectUri, new ClientCredential(Startup.ClientSecret), userTokenCache, null);

                AuthenticationResult result = await cca.AcquireTokenSilentAsync(scope, cca.Users.FirstOrDefault(), Startup.Authority, false);


                HttpClient client = new HttpClient();
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, apiEndpoint + id);

                // Add token to the Authorization header and send 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:
                    case HttpStatusCode.NoContent:
                        return new RedirectResult("/Tasks");
                    case HttpStatusCode.Unauthorized:
                        return ErrorAction("Please sign in again. " + response.ReasonPhrase);
                    default:
                        return ErrorAction("Error. Status code = " + response.StatusCode);
                }
            }
            catch (Exception ex)
            {
                return ErrorAction("Error deleting from list: " + ex.Message);
            }
        }
예제 #5
0
        public async Task JsonWebTokenWithX509PublicCertSendCertificateTestAsync()
        {
            using (var httpManager = new MockHttpManager())
            {
                var serviceBundle = ServiceBundle.CreateWithCustomHttpManager(httpManager);

                SetupMocks(httpManager);
                var certificate = new X509Certificate2(
                    ResourceHelper.GetTestResourceRelativePath("valid_cert.pfx"),
                    MsalTestConstants.DefaultPassword);

                var clientAssertion  = new ClientAssertionCertificate(certificate);
                var clientCredential = new ClientCredential(clientAssertion);
                var app = new ConfidentialClientApplication(
                    serviceBundle,
                    MsalTestConstants.ClientId,
                    ClientApplicationBase.DefaultAuthority,
                    MsalTestConstants.RedirectUri,
                    clientCredential,
                    _cache,
                    _cache)
                {
                    ValidateAuthority = false
                };

                //Check for x5c claim
                httpManager.AddMockHandler(X5CMockHandler);
                AuthenticationResult result =
                    await(app as IConfidentialClientApplicationWithCertificate).AcquireTokenForClientWithCertificateAsync(
                        MsalTestConstants.Scope).ConfigureAwait(false);
                Assert.IsNotNull(result.AccessToken);

                result = await app.AcquireTokenForClientAsync(MsalTestConstants.Scope).ConfigureAwait(false);

                Assert.IsNotNull(result.AccessToken);
            }
        }
        /// <summary>
        /// Gets the current user's access token from the MSAL token cache.
        /// </summary>
        /// <returns>An access token</returns>
        public async Task <string> GetUserAccessTokenAsync()
        {
            string             userId         = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            HttpContextWrapper httpContext    = new HttpContextWrapper(HttpContext.Current);
            TokenCache         userTokenCache = new SessionTokenCache(userId, httpContext).GetMsalCacheInstance();

            ConfidentialClientApplication cca = new ConfidentialClientApplication(
                clientId, redirectUri, new ClientCredential(clientSecret), userTokenCache, null);

            // Attempt to retrieve access token from the cache. Could also make a network call for a new
            // access token if the cached one is expired or close to expiration and a refresh token is
            // available.
            try
            {
                AuthenticationResult result = await cca.AcquireTokenSilentAsync(
                    scopes.Split(new char[] { ' ' }), cca.Users.First());

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

                throw new Microsoft.Graph.ServiceException(
                          new Microsoft.Graph.Error
                {
                    Code    = Microsoft.Graph.GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = "Authentication is required."
                });
            }
        }
예제 #7
0
        public async Task ClientCreds_NonExpired_NeedsRefresh_AADInvalidResponse_Async()
        {
            bool wasErrorLogged = false;

            // Arrange
            using (MockHttpAndServiceBundle harness = base.CreateTestHarness())
            {
                Trace.WriteLine("1. Setup an app");
                ConfidentialClientApplication app = SetupCca(harness, LocalLogCallback);

                Trace.WriteLine("2. Configure AT so that it shows it needs to be refreshed");

                UpdateATWithRefreshOn(app.AppTokenCacheInternal.Accessor);

                TokenCacheAccessRecorder cacheAccess = app.AppTokenCache.RecordAccess();

                Trace.WriteLine("3. Configure AAD to respond with the typical Invalid Grant error");
                harness.HttpManager.AddAllMocks(TokenResponseType.InvalidGrant);

                // Act
                await app.AcquireTokenForClient(TestConstants.s_scope)
                .ExecuteAsync()
                .ConfigureAwait(false);

                Assert.IsTrue(YieldTillSatisfied(() => wasErrorLogged == true));
                cacheAccess.WaitTo_AssertAcessCounts(1, 0);
            }

            void LocalLogCallback(LogLevel level, string message, bool containsPii)
            {
                if (level == LogLevel.Error &&
                    message.Contains(BackgroundFetch_Failed))
                {
                    wasErrorLogged = true;
                }
            }
        }
예제 #8
0
        public async Task ClientCreds_OnBehalfOf_NonExpired_NeedsRefresh_ValidResponse_Async()
        {
            // Arrange
            using (MockHttpAndServiceBundle harness = base.CreateTestHarness())
            {
                Trace.WriteLine("1. Setup an app with a token cache with one AT");
                ConfidentialClientApplication app = SetupCca(harness);

                Trace.WriteLine("2. Configure AT so that it shows it needs to be refreshed");
                var refreshOn = UpdateATWithRefreshOn(app.UserTokenCacheInternal.Accessor).RefreshOn;
                TokenCacheAccessRecorder cacheAccess = app.UserTokenCache.RecordAccess();

                Trace.WriteLine("3. Configure AAD to respond with valid token to the refresh RT flow");
                harness.HttpManager.AddAllMocks(TokenResponseType.Valid_UserFlows);

                // Act
                Trace.WriteLine("4. ATS - should perform an RT refresh");
                AuthenticationResult result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, new UserAssertion(TestConstants.UserAssertion, "assertiontype"))
                                              .ExecuteAsync()
                                              .ConfigureAwait(false);

                // Assert
                YieldTillSatisfied(() => harness.HttpManager.QueueSize == 0);
                Assert.IsNotNull(result);
                Assert.AreEqual(0, harness.HttpManager.QueueSize,
                                "MSAL should have refreshed the token because the original AT was marked for refresh");
                cacheAccess.WaitTo_AssertAcessCounts(1, 1);
                Assert.IsTrue(result.AuthenticationResultMetadata.CacheRefreshReason == CacheRefreshReason.ProactivelyRefreshed);
                Assert.IsTrue(result.AuthenticationResultMetadata.RefreshOn == refreshOn);

                result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, new UserAssertion(TestConstants.UserAssertion, "assertiontype"))
                         .ExecuteAsync()
                         .ConfigureAwait(false);

                Assert.IsTrue(result.AuthenticationResultMetadata.CacheRefreshReason == CacheRefreshReason.NotApplicable);
            }
        }
예제 #9
0
        // Gets an access token. First tries to get the access token from the token cache.
        // Using password (secret) to authenticate. Production apps should use a certificate.
        public async Task <string> GetUserAccessTokenAsync(string userId)
        {
            userTokenCache = new SessionTokenCache(userId, memoryCache).GetCacheInstance();

            var cca = new ConfidentialClientApplication(
                appId,
                redirectUri,
                credential,
                userTokenCache,
                null);

            if (!cca.Users.Any())
            {
                throw new ServiceException(new Error
                {
                    Code    = "TokenNotFound",
                    Message = "User not found in token cache. Maybe the server was restarted."
                });
            }

            try
            {
                var result = await cca.AcquireTokenSilentAsync(scopes, cca.Users.First());

                return(result.AccessToken);
            }

            // Unable to retrieve the access token silently.
            catch (Exception)
            {
                throw new ServiceException(new Error
                {
                    Code    = GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = "Caller needs to authenticate. Unable to retrieve the access token silently."
                });
            }
        }
예제 #10
0
        public void ConfigureAuth(IAppBuilder app)
        {
            ApplicationDbContext db = new ApplicationDbContext();

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                ClientId                  = clientId,
                Authority                 = Authority,
                Scope                     = "openid offline_access profile email " + string.Join(" ", scopes),
                RedirectUri               = postLogoutRedirectUri,
                PostLogoutRedirectUri     = "/",
                TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateIssuer = false
                },
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    AuthorizationCodeReceived = async(context) =>
                    {
                        var code = context.Code;
                        string signedInUserID             = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                        ConfidentialClientApplication cca = new ConfidentialClientApplication(clientId,
                                                                                              postLogoutRedirectUri,
                                                                                              new ClientCredential(appKey),
                                                                                              new MSALTokenCache(signedInUserID));
                        var result = await cca.AcquireTokenByAuthorizationCodeAsync(scopes, code);
                    }
                }
            });
        }
        public void ConstructorsTest()
        {
            ConfidentialClientApplication app = new ConfidentialClientApplication(TestConstants.DefaultClientId,
                                                                                  TestConstants.DefaultRedirectUri, new ClientCredential(TestConstants.DefaultClientSecret), new TokenCache());

            Assert.IsNotNull(app);
            Assert.IsNotNull(app.UserTokenCache);
            Assert.IsNotNull(app.AppTokenCache);
            Assert.AreEqual("https://login.microsoftonline.com/common/", app.Authority);
            Assert.AreEqual(TestConstants.DefaultClientId, app.ClientId);
            Assert.AreEqual(TestConstants.DefaultRedirectUri, app.RedirectUri);
            Assert.AreEqual("https://login.microsoftonline.com/common/", app.Authority);
            Assert.IsNotNull(app.ClientCredential);
            Assert.IsNotNull(app.ClientCredential.Secret);
            Assert.AreEqual(TestConstants.DefaultClientSecret, app.ClientCredential.Secret);
            Assert.IsNull(app.ClientCredential.Certificate);
            Assert.IsNull(app.ClientCredential.ClientAssertion);
            Assert.AreEqual(0, app.ClientCredential.ValidTo);

            app = new ConfidentialClientApplication(TestConstants.DefaultAuthorityGuestTenant,
                                                    TestConstants.DefaultClientId,
                                                    TestConstants.DefaultRedirectUri, new ClientCredential("secret"), new TokenCache());
            Assert.AreEqual(TestConstants.DefaultAuthorityGuestTenant, app.Authority);
        }
예제 #12
0
        public async Task ClientCreds_WithClientAssertion_Adfs_Async()
        {
            var cert = await _keyVault.GetCertificateWithPrivateMaterialAsync(AdfsCertName)
                       .ConfigureAwait(false);

            string clientAssertion =
                GetSignedClientAssertionUsingWilson(Adfs2019LabConstants.Authority, cert);

            ConfidentialClientApplication msalConfidentialClient =
                ConfidentialClientApplicationBuilder.Create(Adfs2019LabConstants.ConfidentialClientId)
                .WithAdfsAuthority(Adfs2019LabConstants.Authority, true)
                .WithRedirectUri(Adfs2019LabConstants.ClientRedirectUri)
                .WithClientAssertion(clientAssertion)
                .BuildConcrete();

            AuthenticationResult authResult = await msalConfidentialClient
                                              .AcquireTokenForClient(s_adfsScopes)
                                              .ExecuteAsync()
                                              .ConfigureAwait(false);

            Assert.IsNotNull(authResult);
            Assert.IsNotNull(authResult.AccessToken);
            Assert.IsNull(authResult.IdToken);
        }
예제 #13
0
        /// <summary>
        /// Get access token for azure active directory application with scope for this application
        /// </summary>
        /// <returns>access token for azure active directory application</returns>
        private async Task <AuthResult> GetAccessTokenForApplicationAsync(string appId, string appSecret, string tenantId, string redirectUri)
        {
            AuthResult result = new AuthResult();

            try
            {
                ConfidentialClientApplication clientApp = new ConfidentialClientApplication(
                    appId,
                    $"https://login.microsoftonline.com/{tenantId}/v2.0",
                    redirectUri,
                    new ClientCredential(appSecret),
                    null,
                    new TokenCache());
                AuthenticationResult authResult = await clientApp.AcquireTokenForClientAsync(new string[] { "https://graph.microsoft.com/.default" });

                result.AccessToken = authResult?.AccessToken;
            }
            catch (Exception err)
            {
                result.Exception = err;
            }

            return(result);
        }
예제 #14
0
        // Gets an access token. First tries to get the token from the token cache.
        public async Task <string> GetApplicationTokenAsync()
        {
            HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current);

            ConfidentialClientApplication cca = new ConfidentialClientApplication(
                appId,
                redirectUri,
                new ClientCredential(appSecret),
                null,
                null);

            try
            {
                AuthenticationResult result = await cca.AcquireTokenForClientAsync(scopes.Split(new char[] { ' ' }));

                return(result.AccessToken);
            }

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

                throw new ServiceException(
                          new Error
                {
                    Code    = GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = Resource.Error_AuthChallengeNeeded,
                });
            }
        }
예제 #15
0
        private static async Task RunObo_Async(MockHttpManager httpManager, ConfidentialClientApplication app)
        {
            httpManager.AddSuccessTokenResponseMockHandlerForPost();
            UserAssertion userAssertion = new UserAssertion(TestConstants.DefaultAccessToken);
            var           result        = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);

            // get AT from cache
            result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.Cache, result.AuthenticationResultMetadata.TokenSource);

            // get AT via OBO flow (no RT cached for OBO)
            TokenCacheHelper.ExpireAllAccessTokens(app.UserTokenCacheInternal);
            var handler = httpManager.AddSuccessTokenResponseMockHandlerForPost();

            handler.ExpectedPostData = new Dictionary <string, string> {
                { OAuth2Parameter.GrantType, OAuth2GrantType.JwtBearer }
            };
            result = await app.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
        }
        // this is how you get tokens obtained by the OIDC middleware
        //private Task<string> GetAccessTokenAsync()
        //{
        //    return httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        //}

        // this is how you get tokens with MSAL
        private async Task <string> GetAccessTokenAsync()
        {
            try
            {
                var principal = httpContextAccessor.HttpContext.User;

                var tokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache();
                var client     = new ConfidentialClientApplication(authOptions.ClientId,
                                                                   authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value),
                                                                   "https://app", // it's not really needed
                                                                   new ClientCredential(authOptions.ClientSecret),
                                                                   tokenCache,
                                                                   null);

                var result = await client.AcquireTokenSilentAsync(new[] { $"{authOptions.ApiIdentifier}/read_values" },
                                                                  client.Users.FirstOrDefault());

                return(result.AccessToken);
            }
            catch (MsalUiRequiredException)
            {
                throw new ReauthenticationRequiredException();
            }
        }
        private static GraphServiceClient GetAuthenticatedClient()
        {
            return(new GraphServiceClient(
                       new DelegateAuthenticationProvider(
                           async(requestMessage) =>
            {
                // Get the signed in user's id and create a token cache
                string signedInUserId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
                SessionTokenStore tokenStore = new SessionTokenStore(signedInUserId,
                                                                     new HttpContextWrapper(HttpContext.Current));

                var idClient = new ConfidentialClientApplication(
                    appId, redirectUri, new ClientCredential(appSecret),
                    tokenStore.GetMsalCacheInstance(), null);

                // By calling this here, the token can be refreshed
                // if it's expired right before the Graph call is made
                var result = await idClient.AcquireTokenSilentAsync(
                    graphScopes.Split(' '), idClient.Users.First());

                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue("Bearer", result.AccessToken);
            })));
        }
        public async Task <string> GetAccessToken(HttpContextBase httpContextBase)
        {
            string accessToken = null;

            // Load the app config from web.config
            var appId       = ConfigurationManager.AppSettings["ida:AppId"];
            var appPassword = ConfigurationManager.AppSettings["ida:AppPassword"];
            var redirectUri = ConfigurationManager.AppSettings["ida:RedirectUri"];
            var scopes      = ConfigurationManager.AppSettings["ida:AppScopes"]
                              .Replace(' ', ',').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            // Get the current user's ID
            var userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;

            if (!string.IsNullOrEmpty(userId))
            {
                // Get the user's token cache
                var tokenCache = new SessionTokenCache(userId, httpContextBase);

                var confidentialClientApplication = new ConfidentialClientApplication(
                    appId,
                    redirectUri,
                    new ClientCredential(appPassword),
                    tokenCache.GetMsalCacheInstance(),
                    null);

                // Call AcquireTokenSilentAsync, which will return the cached
                // access token if it has not expired. If it has expired, it will
                // handle using the refresh token to get a new one.
                var result = await confidentialClientApplication.AcquireTokenSilentAsync(scopes, confidentialClientApplication.Users.First());

                accessToken = result.AccessToken;
            }

            return(accessToken);
        }
예제 #19
0
        /// <summary>
        ///     A helper method to create a ConfidentialClientApplication
        ///     required to retrieve the token that is needed to be attached
        ///     as a Bearer Token to a Request.
        ///     <para>
        ///         This code is for an AAD (it's using AuthenticationUri, rather than .AuthorityCookieConfigurationPolicyUri)
        ///     </para>
        /// </summary>
        public ConfidentialClientApplication CreateConfidentialClientApplication(
            HttpContextBase httpContextBase,
            string authorityUriOverride,
            IOidcSettingsConfidentialClientConfiguration oidcSettingsConfidentialClientConfiguration,
            params string[] fqScopes)
        {
            // ** IMPORTANT**
            // The calls to AAD and B2C are mostly the same bar the following:
            // For AAD, use .AuthorityUri
            var        authorityUri           = authorityUriOverride ?? oidcSettingsConfidentialClientConfiguration.AuthorityUri;
            var        signedInUserIdentifier = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
            var        userTokenCache         = new MSALSessionCache(signedInUserIdentifier, httpContextBase).GetMsalCacheInstance();
            TokenCache appTokenCache          = null;

            var confidentialClientApplication = new ConfidentialClientApplication(
                oidcSettingsConfidentialClientConfiguration.ClientId,
                authorityUri /*note...*/,
                oidcSettingsConfidentialClientConfiguration.ClientRedirectUri,
                new ClientCredential(oidcSettingsConfidentialClientConfiguration.ClientSecret),
                userTokenCache,
                appTokenCache);

            return(confidentialClientApplication);
        }
        public async Task ClientCreds_NonExpired_NeedsRefresh_AADInvalidResponse_Async()
        {
            // Arrange
            using (MockHttpAndServiceBundle harness = base.CreateTestHarness())
            {
                Trace.WriteLine("1. Setup an app with a token cache with one AT");
                ConfidentialClientApplication app = SetupCca(harness);

                Trace.WriteLine("2. Configure AT so that it shows it needs to be refreshed");
                UpdateATWithRefreshOn(app.AppTokenCacheInternal.Accessor, DateTime.UtcNow - TimeSpan.FromMinutes(1));
                TokenCacheAccessRecorder cacheAccess = app.AppTokenCache.RecordAccess();

                Trace.WriteLine("3. Configure AAD to respond with the typical Invalid Grant error");
                AddHttpMocks(TokenResponseType.Invalid_AADAvailable, harness.HttpManager, pca: false);

                // Act
                await AssertException.TaskThrowsAsync <MsalUiRequiredException>(() =>
                                                                                app.AcquireTokenForClient(TestConstants.s_scope)
                                                                                .ExecuteAsync())
                .ConfigureAwait(false);

                cacheAccess.AssertAccessCounts(1, 0);
            }
        }
            public async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
            {
                // Use MSAL to swap the code for an access token
                // Extract the code from the response notification
                var code = context.ProtocolMessage.Code;

                string     signedInUserID         = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
                TokenCache userTokenCache         = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
                ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);

                cca.ValidateAuthority = false;
                try
                {
                    AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' '));


                    context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                }
                catch (Exception ex)
                {
                    //TODO: Handle
                    throw;
                }
            }
 /// <summary>
 /// Generate a certificate. Create a Confidential Client Application with that certificate and
 /// an AcquireTokenForClient call to benchmark.
 /// </summary>
 public CryptoManagerTests()
 {
     _httpManager = new MockHttpManager();
     _httpManager.MessageHandlerFunc = () => new MockHttpMessageHandler()
     {
         ExpectedMethod  = HttpMethod.Post,
         ResponseMessage = MockHelpers.CreateSuccessfulClientCredentialTokenResponseMessage()
     };
     _requests = new AcquireTokenForClientParameterBuilder[AppsCount];
     for (int i = 0; i < AppsCount; i++)
     {
         X509Certificate2 certificate = CreateCertificate("CN=rsa2048", RSA.Create(2048), HashAlgorithmName.SHA256, null);
         _cca = ConfidentialClientApplicationBuilder
                .Create(TestConstants.ClientId)
                .WithAuthority(new Uri(TestConstants.AuthorityTestTenant))
                .WithRedirectUri(TestConstants.RedirectUri)
                .WithCertificate(certificate)
                .WithHttpManager(_httpManager)
                .BuildConcrete();
         AddHostToInstanceCache(_cca.ServiceBundle, TestConstants.ProductionPrefNetworkEnvironment);
         _requests[_requestIdx] = _cca.AcquireTokenForClient(TestConstants.s_scope)
                                  .WithForceRefresh(true);
     }
 }
예제 #23
0
        public async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context, string clientId, string authority, string clientSecret, string redirectUri, string apiScopes)
        {
            // Use MSAL to swap the code for an access token
            // Extract the code from the response notification
            var code = context.ProtocolMessage.Code;

            var signedInUserId = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
            var userTokenCache = new MsalSessionCache(signedInUserId, context.HttpContext).GetMsalCacheInstance();
            var cca            = new ConfidentialClientApplication(clientId, authority, redirectUri, new ClientCredential(clientSecret), userTokenCache, null);

            try
            {
                var result =
                    await cca.AcquireTokenByAuthorizationCodeAsync(code, apiScopes.Split(' '));


                context.HandleCodeRedemption(result.AccessToken, result.IdToken);
            }
            catch (Exception ex)
            {
                //TODO: Handle
                throw;
            }
        }
예제 #24
0
        // Gets 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;
            HttpContextWrapper httpContext    = new HttpContextWrapper(HttpContext.Current);
            TokenCache         userTokenCache = new SessionTokenCache(signedInUserID, httpContext).GetMsalCacheInstance();
            //var cachedItems = tokenCache.ReadItems(appId); // see what's in the cache

            ConfidentialClientApplication cca = new ConfidentialClientApplication(
                appId,
                redirectUri,
                new ClientCredential(appSecret),
                userTokenCache,
                null);

            try
            {
                var accounts = await cca.GetAccountsAsync();

                AuthenticationResult result = await cca.AcquireTokenSilentAsync(scopes.Split(new char[] { ' ' }), accounts.First());

                return(result.AccessToken);
            }

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

                throw new Exception("Caller needs to authenticate.");
            }
        }
        /// <summary>
        /// Gets an access token for a downstream API on behalf of the user which account ID is passed as an argument
        /// </summary>
        /// <param name="accountIdentifier">User account identifier for which to acquire a token.
        /// See <see cref="Microsoft.Identity.Client.AccountId.Identifier"/></param>
        /// <param name="scopes">Scopes for the downstream API to call</param>
        private async Task <string> GetAccessTokenOnBehalfOfUser(ConfidentialClientApplication application, string accountIdentifier, IEnumerable <string> scopes, string loginHint)
        {
            if (accountIdentifier == null)
            {
                throw new ArgumentNullException(nameof(accountIdentifier));
            }

            if (scopes == null)
            {
                throw new ArgumentNullException(nameof(scopes));
            }

            // Get the account
            IAccount account = await application.GetAccountAsync(accountIdentifier);

            // Special case for guest users as the Guest iod / tenant id are not surfaced.
            if (account == null)
            {
                var accounts = await application.GetAccountsAsync();

                account = accounts.FirstOrDefault(a => a.Username == loginHint);
            }

            try
            {
                AuthenticationResult result = null;
                result = await application.AcquireTokenSilentAsync(scopes.Except(scopesRequestedByMsalNet), account);

                return(result.AccessToken);
            }
            catch (MsalException)
            {
                // TODO process the exception see if this is retryable etc ...
                throw;
            }
        }
예제 #26
0
 public MsalAuthenticationProvider(ConfidentialClientApplication clientApplication, string[] scopes)
 {
     _clientApplication = clientApplication;
     _scopes            = scopes;
 }
        public static async Task <string> GenerateAuthorizationRequestUrl(string[] scopes, ConfidentialClientApplication cca, HttpContextBase httpcontext, UrlHelper url)
        {
            string signedInUserID          = ClaimsPrincipal.Current.FindFirst(System.IdentityModel.Claims.ClaimTypes.NameIdentifier).Value;
            string preferredUsername       = ClaimsPrincipal.Current.FindFirst("upn").Value;
            Uri    oauthCodeProcessingPath = new Uri(httpcontext.Request.Url.GetLeftPart(UriPartial.Authority).ToString());
            string state           = GenerateState(httpcontext.Request.Url.ToString(), httpcontext, url, scopes);
            string tenantID        = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
            string domain_hint     = (tenantID == "9188040d-6c67-4c5b-b112-36a304b66dad") ? "consumers" : "organizations";
            Uri    authzMessageUri =
                await cca.GetAuthorizationRequestUrlAsync(
                    scopes,
                    oauthCodeProcessingPath.ToString(),
                    preferredUsername,
                    state == null?null : "&state=" + state + "&domain_hint=" + domain_hint,
                    null,
                    // TODo change
                    cca.Authority
                    );

            return(authzMessageUri.ToString());
        }
예제 #28
0
        /*
         * Callback function when an authorization code is received
         */

        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
        {
            notification.AuthenticationTicket.Properties.ExpiresUtc   = DateTime.UtcNow.AddMinutes(AuthTicketExpiresInMinutes);
            notification.AuthenticationTicket.Properties.AllowRefresh = AuthTicketAllowRefresh;

            HttpContext.Current.User = new ClaimsPrincipal(notification.AuthenticationTicket.Identity);
            // Extract the code from the response notification
            var    code           = notification.Code;
            string signedInUserId = notification.AuthenticationTicket.Identity.FindFirst("userId").Value;

            //ClaimTypes.NameIdentifier).Value;

            TokenCache userTokenCache = new MSALSessionCache(signedInUserId, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance(); //CacheFactoryFunc().Invoke();//
            //TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();

            ConfidentialClientApplication context = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
            AuthenticationResult          user    = await context.AcquireTokenByAuthorizationCodeAsync(code, new[] { Scopes });

            //HttpContext.Current.GetOwinContext().Environment["System.Web.HttpContextBase"] = notification.OwinContext.Environment["System.Web.HttpContextBase"];


            //check policy
            string fullPatch  = notification.AuthenticationTicket.Properties.RedirectUri;
            string tenantName = fullPatch.Split('/').Where(x => x.Length > 0).ToList()[2];
            Tenant tenant     = _dbContext.Tenants.FirstOrDefault(x => x.DomainName.ToLower() == tenantName.ToLower());

            if (tenant == null)
            {
                return;
            }

            if (tenant.DomainName.ToLower() == "Admin".ToLower())
            {
                _serviceId = ConfigurationManager.AppSettings["ServiceId"];
            }
            else
            {
                TenantInfo tenantInfo = _dbContext.TenantInfos.FirstOrDefault(x => x.TenantId == tenant.Id && x.Key == "MyDNVGLServiceId");
                if (tenantInfo != null && !string.IsNullOrEmpty(tenantInfo.Value))
                {
                    _serviceId = tenantInfo.Value;
                }
            }

            if (string.IsNullOrEmpty(_serviceId))
            {
                return;
            }

            var policy = new Policy();

            try
            {
                policy = await _veracityApiHelper.GetPolicyModel(user.AccessToken, _serviceId);
            }
            catch
            {
                notification.OwinContext.Authentication.SignOut();
                return;
            }

            if ((HttpStatusCode)policy.statusCode == HttpStatusCode.NoContent)
            {
                //add local roles
                var     ctx         = HttpContext.Current.GetOwinContext();
                string  myDnvglId   = ctx.Authentication.User.Claims.FirstOrDefault(x => x.Type == "userId")?.Value;
                var     tenantId    = _dbContext.Tenants.FirstOrDefault(x => x.DomainName.ToLower() == tenantName.ToLower())?.Id;
                AppUser loginedUser = _dbContext.AppUsers.FirstOrDefault(u => u.MyDnvglUserId == myDnvglId && u.TenantId == tenantId);
                if (loginedUser == null)
                {
                    return;
                }
                var roles = _dbContext.AppUsers.FirstOrDefault(u => u.Id == loginedUser.Id && u.TenantId == loginedUser.TenantId)?.Roles.Select(r => r.RoleId).ToList();

                var claims = notification.AuthenticationTicket.Identity;
                foreach (var role in roles)
                {
                    claims.AddClaim(new Claim(ClaimTypes.Role, role));
                }

                //Replace claim's 'userId' from MyDnvglId to local UserID
                claims.RemoveClaim(claims.FindFirst(ClaimTypes.NameIdentifier));
                claims.AddClaim(new Claim(ClaimTypes.NameIdentifier, loginedUser.Id));

                //add access token into claims
                claims.AddClaim(new Claim("AccessToken", user.AccessToken));

                notification.OwinContext.Authentication.SignIn(new AuthenticationProperties {
                    IsPersistent = true, ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10)
                }, claims);
            }
            else
            {
                notification.OwinContext.Authentication.SignOut();
                string strRedirectUrl         = policy.url;
                bool   isHaveEmptyRedirectUrl =
                    strRedirectUrl.Split(new string[] { "?", "&" }, StringSplitOptions.None)
                    .Any(x => x.Equals("returnUrl="));
                if (isHaveEmptyRedirectUrl)
                {
                    strRedirectUrl = strRedirectUrl.Replace("returnUrl=", "returnUrl=" + fullPatch);
                }
                HttpContext.Current.Response.Redirect(strRedirectUrl);
            }

            //AppUser testUser = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<AppUser>>().FindByName(notification.Request.User.GetPowerBIAppAuthenticationIdentity().GetUserName());

            //try
            //{
            //    //await ClientFactory.CreateClient(RedirectUri).My.ValidatePolicies();
            //    notification.OwinContext.Authentication.SignIn(notification.AuthenticationTicket.Identity);
            //}
            //catch (ServerException ex)
            //{
            //    //if (ex.Status == HttpStatusCode.NotAcceptable)
            //    //{
            //    //    notification.Response.Redirect(ex.GetErrorData<ValidationError>().Url); //Getting the redirect url from the error message.
            //    //    notification.HandleResponse(); //Mark the notification as handled to allow the redirect to happen.
            //    //}
            //}
        }
예제 #29
0
        public void ConfigureAuth(IAppBuilder app)
        {
            Debug.WriteLine("Print from configureAuth function in startup_auth.cs");

            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());

            app.UseOAuth2CodeRedeemer(
                new OAuth2CodeRedeemerOptions
            {
                ClientId     = appId,
                ClientSecret = appSecret,
                RedirectUri  = redirectUri
            }
                );

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
            {
                // The `Authority` represents the v2.0 endpoint - https://login.microsoftonline.com/common/v2.0
                // The `Scope` describes the permissions that your app will need. See https://azure.microsoft.com/documentation/articles/active-directory-v2-scopes/
                ClientId                  = appId,
                Authority                 = String.Format(CultureInfo.InvariantCulture, aadInstance, "common", "/v2.0"),
                RedirectUri               = redirectUri,
                Scope                     = scopes,
                PostLogoutRedirectUri     = redirectUri,
                TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = false,
                    // In a real application you would use IssuerValidator for additional checks,
                    // like making sure the user's organization has signed up for your app.
                    //     IssuerValidator = (issuer, token, tvp) =>
                    //     {
                    //         if (MyCustomTenantValidation(issuer))
                    //             return issuer;
                    //         else
                    //             throw new SecurityTokenInvalidIssuerException("Invalid issuer");
                    //     },
                },
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthorizationCodeReceived = async(context) =>
                    {
                        var code = context.Code;
                        //string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
                        string graphScopes = nonAdminScopes;
                        string[] scopes    = graphScopes.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        string signedInUserID = System.Web.HttpContext.Current.Session["currentUserId"] as String;

                        ConfidentialClientApplication cca = new ConfidentialClientApplication(appId, redirectUri,
                                                                                              new ClientCredential(appSecret),
                                                                                              new EFTokenCache(signedInUserID, context.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance(), null);
                        AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, scopes);

                        context.HandleResponse();
                        context.Response.Redirect("/Home/ShowMessage?message=" + "Authentication SUCCESSFULLY");


                        // Check whether the login is from the MSA tenant.
                        // The sample uses this attribute to disable UI buttons for unsupported operations when the user is logged in with an MSA account.
                        //var currentTenantId = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
                        //if (currentTenantId == "9188040d-6c67-4c5b-b112-36a304b66dad")
                        //{
                        //    HttpContext.Current.Session.Add("AccountType", "msa");
                        //}
                        //// Set IsAdmin session variable to false, since the user hasn't consented to admin scopes yet.
                        //HttpContext.Current.Session.Add("IsAdmin", false);
                    },
                    AuthenticationFailed = (context) =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("/Error?message=" + context.Exception.Message);
                        return(Task.FromResult(0));
                    }
                }
            });
        }
 /// <summary>
 /// Constructs the configuration properties used to construct a proof of possession request
 /// </summary>
 /// <param name="requestUri">An Uri to the protected resource which requires a PoP token. The PoP token will be cryptographically bound to the request uri</param>
 public PoPAuthenticationConfiguration(Uri requestUri)
 {
     ConfidentialClientApplication.GuardMobileFrameworks();
     RequestUri = requestUri ?? throw new ArgumentNullException(nameof(requestUri));
 }