Beispiel #1
0
        public async Task AcquireTokenByObo_LongRunning_WithDifferentScopes_TestAsync()
        {
            string[] scopes2 = { "api://eec635da-5760-452d-940a-448220db047c/access_as_user" };
            var      user1   = (await LabUserHelper.GetSpecificUserAsync("*****@*****.**").ConfigureAwait(false)).User;
            var      pca     = PublicClientApplicationBuilder
                               .Create(PublicClientID)
                               .WithAuthority(AadAuthorityAudience.AzureAdMultipleOrgs)
                               .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                               .Build();

            var userAuthResult = await pca
                                 .AcquireTokenByUsernamePassword(s_oboServiceScope, user1.Upn, new NetworkCredential("", user1.GetOrFetchPassword()).SecurePassword)
                                 .ExecuteAsync(CancellationToken.None)
                                 .ConfigureAwait(false);

            var cca = BuildCCA(userAuthResult.TenantId);

            string        oboCacheKey   = "obo-cache-key";
            UserAssertion userAssertion = new UserAssertion(userAuthResult.AccessToken);

            var result = await cca.InitiateLongRunningProcessInWebApi(s_scopes, userAuthResult.AccessToken, ref oboCacheKey)
                         .ExecuteAsync().ConfigureAwait(false);

            // Cache has 1 partition (user-provided key) with 1 token
            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllAccessTokens().Count);
            Assert.AreEqual(1, cca.UserTokenCacheInternal.Accessor.GetAllRefreshTokens().Count);

            // No matching AT, uses RT to retrieve new AT.
            result = await cca.AcquireTokenInLongRunningProcess(scopes2, oboCacheKey).ExecuteAsync().ConfigureAwait(false);

            Assert.AreEqual(TokenSource.IdentityProvider, result.AuthenticationResultMetadata.TokenSource);
            Assert.AreEqual(CacheRefreshReason.NoCachedAccessToken, result.AuthenticationResultMetadata.CacheRefreshReason);
        }
Beispiel #2
0
        public async Task <AuthenticationResult> AcquireTokenBySsoTokenOnBehalfOf(string ssoToken, string[] scopes)
        {
            try
            {
                _logger.LogDebug("Acquiring token via OBO flow.");
                var userAssertion = new UserAssertion(ssoToken);
                var app           = BuildConfidentialClientApplication();
                var result        = await app.AcquireTokenOnBehalfOf(scopes, userAssertion)
                                    .ExecuteAsync()
                                    .ConfigureAwait(false);

                return(result);
            }
            catch (MsalUiRequiredException ex) // Need user interaction
            {
                throw new AadUiRequiredException(ex.Message, ex);
            }
            catch (MsalServiceException ex) // Errors that returned from AAD service
            {
                throw generateAadException(ex.ResponseBody, (HttpStatusCode)ex.StatusCode, ex);
            }
            catch (MsalClientException ex) // Exceptions that are local to the MSAL library
            {
                throw new AuthInternalServerException(ex.Message, ex);
            }
        }
Beispiel #3
0
        public static async Task <string> GetTokenOnBehalfOfAsync(string authHeader)
        {
            if (string.IsNullOrEmpty(authHeader))
            {
                throw new AdalException("missing_auth", "Authorization header is not present on request.");
            }

            // Parse the auth header
            var parsedHeader = AuthenticationHeaderValue.Parse(authHeader);

            if (parsedHeader.Scheme.ToLower() != "bearer")
            {
                throw new AdalException("invalid_scheme", "Authorization header is missing the 'bearer' scheme.");
            }

            // Create an assertion based on the provided token
            var userAssertion = new UserAssertion(parsedHeader.Parameter, "urn:ietf:params:oauth:grant-type:jwt-bearer");
            var authContext   = new AuthenticationContext(authority);

            // Exchange the provided token for a Graph token
            var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com",
                                                             clientCreds, userAssertion);

            return(result.AccessToken);
        }
Beispiel #4
0
        public static async Task GetTokenOnBehalfOfAsync(string authHeader, ILogger log)
        {
            logger = log;
            if (string.IsNullOrEmpty(authHeader))
            {
                throw new MsalException("missing_auth", "Authorization header is not present on request.");
            }

            // Parse the auth header
            var parsedHeader = AuthenticationHeaderValue.Parse(authHeader);

            if (parsedHeader.Scheme.ToLower() != "bearer")
            {
                throw new MsalException("invalid_scheme", "Authorization header is missing the 'bearer' scheme.");
            }

            var confidentialClient = new ConfidentialClientApplication(notifAppId,
                                                                       authority, redirectUri, notifClientCreds, BlobTokenCache.GetMsalCacheInstance(), null);

            //Logger.LogCallback = AuthLog;
            //Logger.Level = Microsoft.Identity.Client.LogLevel.Verbose;
            //Logger.PiiLoggingEnabled = true;
            var userAssertion = new UserAssertion(parsedHeader.Parameter);

            try
            {
                var result = await confidentialClient.AcquireTokenOnBehalfOfAsync(notifScopes, userAssertion);
            }
            catch (Exception ex)
            {
                logger.LogError($"Error getting OBO token: {ex.Message}");
                throw ex;
            }
        }
Beispiel #5
0
        private Dictionary <string, string> GetAdditionalBodyParameters(UserAssertion userAssertion)
        {
            var dict = new Dictionary <string, string>();

            if (userAssertion != null)
            {
                dict[OAuth2Parameter.GrantType] = userAssertion.AssertionType;
                dict[OAuth2Parameter.Assertion] = Convert.ToBase64String(Encoding.UTF8.GetBytes(userAssertion.Assertion));
            }

            // This is hit if the account is managed, as no userAssertion is created for a managed account
            else
            {
                dict[OAuth2Parameter.GrantType] = OAuth2GrantType.Password;
                dict[OAuth2Parameter.Username]  = _usernamePasswordParameters.Username;
                dict[OAuth2Parameter.Password]  = new string(_usernamePasswordParameters.Password.PasswordToCharArray());
            }

            ISet <string> unionScope = new HashSet <string>()
            {
                OAuth2Value.ScopeOpenId,
                OAuth2Value.ScopeOfflineAccess,
                OAuth2Value.ScopeProfile
            };

            unionScope.UnionWith(AuthenticationRequestParameters.Scope);
            dict[OAuth2Parameter.Scope] = unionScope.AsSingleString();

            return(dict);
        }
Beispiel #6
0
        internal override async Task PreTokenRequest()
        {
            await base.PreTokenRequest().ConfigureAwait(false);

            if (this.PerformUserRealmDiscovery())
            {
                UserRealmDiscoveryResponse userRealmResponse = await UserRealmDiscoveryResponse.CreateByDiscoveryAsync(this.Authenticator.UserRealmUri, this.userCredential.UserName, this.CallState).ConfigureAwait(false);

                PlatformPlugin.Logger.Information(this.CallState, string.Format("User with hash '{0}' detected as '{1}'", PlatformPlugin.CryptographyHelper.CreateSha256Hash(this.userCredential.UserName), userRealmResponse.AccountType));

                if (string.Compare(userRealmResponse.AccountType, "federated", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (string.IsNullOrWhiteSpace(userRealmResponse.FederationMetadataUrl))
                    {
                        throw new MsalException(MsalError.MissingFederationMetadataUrl);
                    }

                    WsTrustAddress wsTrustAddress = await MexParser.FetchWsTrustAddressFromMexAsync(userRealmResponse.FederationMetadataUrl, this.userCredential.UserAuthType, this.CallState).ConfigureAwait(false);

                    PlatformPlugin.Logger.Information(this.CallState, string.Format("WS-Trust endpoint '{0}' fetched from MEX at '{1}'", wsTrustAddress.Uri, userRealmResponse.FederationMetadataUrl));

                    WsTrustResponse wsTrustResponse = await WsTrustRequest.SendRequestAsync(wsTrustAddress, this.userCredential, this.CallState).ConfigureAwait(false);

                    PlatformPlugin.Logger.Information(this.CallState, string.Format("Token of type '{0}' acquired from WS-Trust endpoint", wsTrustResponse.TokenType));

                    // We assume that if the response token type is not SAML 1.1, it is SAML 2
                    this.userAssertion = new UserAssertion(wsTrustResponse.Token, (wsTrustResponse.TokenType == WsTrustResponse.Saml1Assertion) ? OAuthGrantType.Saml11Bearer : OAuthGrantType.Saml20Bearer, this.userCredential.UserName);
                }
                else
                {
                    throw new MsalException(MsalError.UnsupportedUserType);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Adds an account to the token cache from a JWT token and other parameters related to the token cache implementation
        /// </summary>
        private void AddAccountToCacheFromJwt(IEnumerable <string> scopes, JwtSecurityToken jwtToken, AuthenticationProperties properties, ClaimsPrincipal principal, HttpContext httpContext)
        {
            try
            {
                UserAssertion        userAssertion;
                IEnumerable <string> requestedScopes;
                if (jwtToken != null)
                {
                    userAssertion   = new UserAssertion(jwtToken.RawData, "urn:ietf:params:oauth:grant-type:jwt-bearer");
                    requestedScopes = scopes ?? jwtToken.Audiences.Select(a => $"{a}/.default");
                }
                else
                {
                    throw new ArgumentOutOfRangeException("tokenValidationContext.SecurityToken should be a JWT Token");
                    // TODO: Understand if we could support other kind of client assertions (SAML);
                }

                var application = CreateApplication(httpContext, principal, properties, null);

                // Synchronous call to make sure that the cache is filled-in before the controller tries to get access tokens
                AuthenticationResult result = application.AcquireTokenOnBehalfOfAsync(scopes.Except(_scopesRequestedByMsalNet), userAssertion).GetAwaiter().GetResult();
            }
            catch (MsalUiRequiredException ex)
            {
                ReplyForbiddenWithWwwAuthenticateHeader(httpContext, scopes, ex);
            }
            catch (MsalException ex)
            {
                string message = ex.Message;
                throw;
            }
        }
        private async Task <string> GetAccessToken(string[] graphScopes)
        {
            string        bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext.ToString();
            UserAssertion userAssertion    = new UserAssertion(bootstrapContext);

            string authority = String.Format(ConfigurationManager.AppSettings["Authority"], ConfigurationManager.AppSettings["DirectoryID"]);

            string appID     = ConfigurationManager.AppSettings["ClientID"];
            string appSecret = ConfigurationManager.AppSettings["ClientSecret"];
            var    cca       = ConfidentialClientApplicationBuilder.Create(appID)
                               .WithRedirectUri("https://localhost:44397")
                               .WithClientSecret(appSecret)
                               .WithAuthority(authority)
                               .Build();
            AcquireTokenOnBehalfOfParameterBuilder parameterBuilder = null;
            AuthenticationResult authResult = null;

            try
            {
                parameterBuilder = cca.AcquireTokenOnBehalfOf(graphScopes, userAssertion);
                authResult       = await parameterBuilder.ExecuteAsync();

                return(authResult.AccessToken);
            }
            catch (MsalServiceException e)
            {
                return(null);
            }
        }
Beispiel #9
0
        public async Task OnBehalfOfProvider_ShouldGetCachedAccessTokenForUserAssertion()
        {
            UserAssertion      assertion          = new UserAssertion(_jwtAccessToken);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.org/foo");

            httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), new GraphRequestContext
            {
                MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new MsalAuthenticationProviderOption
                            {
                                UserAssertion = assertion
                            }
                        }
                    }
                }
            });

            OnBehalfOfProvider authProvider = new OnBehalfOfProvider(_mockClientApplicationBase.Object, _scopes);
            await authProvider.AuthenticateRequestAsync(httpRequestMessage);

            Assert.IsInstanceOfType(authProvider.ClientApplication, typeof(IConfidentialClientApplication), "Unexpected client application set.");
            Assert.IsNotNull(httpRequestMessage.Headers.Authorization, "Unexpected auhtorization header set.");
            Assert.AreEqual(_silentAuthResult.AccessToken, httpRequestMessage.Headers.Authorization.Parameter, "Unexpected access token set.");
        }
        public async Task AcquireTokenByOboAccessTokenInCacheTestAsync()
        {
            using (var httpManager = new MockHttpManager())
            {
                httpManager.AddInstanceDiscoveryMockHandler();

                AddMockHandlerAadSuccess(httpManager, TestConstants.AuthorityCommonTenant);

                var cca = ConfidentialClientApplicationBuilder
                          .Create(TestConstants.ClientId)
                          .WithClientSecret(TestConstants.ClientSecret)
                          .WithAuthority(TestConstants.AuthorityCommonTenant)
                          .WithHttpManager(httpManager)
                          .BuildConcrete();

                UserAssertion userAssertion = new UserAssertion(TestConstants.DefaultAccessToken);
                var           result        = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);

                result = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual(result.AuthenticationResultMetadata.TokenSource, TokenSource.Cache);
                Assert.AreEqual("some-access-token", result.AccessToken);
            }
        }
        public async Task AcquireTokenByOboMissMatchUserAssertionsAsync()
        {
            using (var httpManager = new MockHttpManager())
            {
                httpManager.AddInstanceDiscoveryMockHandler();

                AddMockHandlerAadSuccess(httpManager, TestConstants.AuthorityCommonTenant);

                var cca = ConfidentialClientApplicationBuilder
                          .Create(TestConstants.ClientId)
                          .WithClientSecret(TestConstants.ClientSecret)
                          .WithAuthority(TestConstants.AuthorityCommonTenant)
                          .WithHttpManager(httpManager)
                          .BuildConcrete();

                UserAssertion userAssertion = new UserAssertion(TestConstants.DefaultAccessToken);
                var           result        = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);

                //Update user assertions
                TokenCacheHelper.UpdateUserAssertions(cca);

                MockHttpMessageHandler mockTokenRequestHttpHandlerRefresh = AddMockHandlerAadSuccess(httpManager, TestConstants.AuthorityCommonTenant);

                //Access and refresh tokens are have a different user assertion so MSAL should perform OBO.
                result = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);
                Assert.AreEqual(result.AuthenticationResultMetadata.TokenSource, TokenSource.IdentityProvider);
            }
        }
Beispiel #12
0
        public async Task InteractiveAuthProvider_ShouldGetNewAccessTokenWithNoIAccount()
        {
            UserAssertion      assertion          = new UserAssertion("access_token");
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.org/foo");

            httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), new GraphRequestContext
            {
                MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new MsalAuthenticationProviderOption
                            {
                                UserAssertion = assertion
                            }
                        }
                    }
                }
            });

            AuthenticationResult newAuthResult = MockAuthResult.GetAuthenticationResult();

            _mockClientApplicationBase.Setup((pca) => pca.AcquireTokenAsync(_scopes, It.IsAny <IAccount>(), UIBehavior.SelectAccount, null, null, _commonAuthority, null))
            .ReturnsAsync(newAuthResult);

            InteractiveAuthenticationProvider authProvider = new InteractiveAuthenticationProvider(_mockClientApplicationBase.Object, _scopes);
            await authProvider.AuthenticateRequestAsync(httpRequestMessage);

            Assert.IsInstanceOfType(authProvider.ClientApplication, typeof(IPublicClientApplication), "Unexpected client application set.");
            Assert.IsNotNull(httpRequestMessage.Headers.Authorization, "Unexpected auhtorization header set.");
            Assert.AreEqual(newAuthResult.AccessToken, httpRequestMessage.Headers.Authorization.Parameter, "Unexpected access token set.");
        }
Beispiel #13
0
        public async Task <string> GetTokenOnBehalfOfAsync()
        {
            try
            {
                const string siteUrl = "localhost:44334";                // "proposalcreation.azurewebsites.net"; //localhost:44334
                // Get the raw token that the add-in page received from the Office host.
                var bootstrapContext = ((ClaimsIdentity)contextAccessor.HttpContext.User.Identity).BootstrapContext.ToString();

                UserAssertion userAssertion = new UserAssertion(bootstrapContext);

                // Get the access token for MS Graph.
                ClientCredential clientCred       = new ClientCredential(this.secret);
                ConfidentialClientApplication cca =
                    new ConfidentialClientApplication(appId,
                                                      $"https://{siteUrl}", clientCred, null, null);

                // The AcquireTokenOnBehalfOfAsync method will first look in the MSAL in memory cache for a
                // matching access token. Only if there isn't one, does it initiate the "on behalf of" flow
                // with the Azure AD V2 endpoint.
                AuthenticationResult result = await cca.AcquireTokenOnBehalfOfAsync(scopes, userAssertion, "https://login.microsoftonline.com/common/oauth2/v2.0");

                return(result.AccessToken);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Beispiel #14
0
        private async Task <string> GetRefreshedToken(string accessToken, Dictionary <string, object> claim)
        {
            _logger.LogDebug("Get refresh token for user access token.");
            try
            {
                var confidentialApp = ConfidentialClientApplicationBuilder
                                      .Create(_bindingAttribute.ClientId)
                                      .WithClientSecret(_bindingAttribute.ClientSecret)
                                      .WithAuthority(_bindingAttribute.OAuthAuthority)
                                      .Build();
                var userAssertion     = new UserAssertion(accessToken.Substring(Constants.BearerScheme.Length + 1));
                var accessAsUserScope = new string[] { _bindingAttribute.ClientId + "/" + Constants.AccessAsUserScope };
                var loginHint         = GetUserLoginHint(claim);
                await confidentialApp.AcquireTokenOnBehalfOf(accessAsUserScope, userAssertion).ExecuteAsync().ConfigureAwait(false); // Get the refresh token

                var refreshedToken = await confidentialApp.AcquireTokenSilent(accessAsUserScope, loginHint)
                                     .WithForceRefresh(true).ExecuteAsync().ConfigureAwait(false);

                return(refreshedToken.AccessToken);
            }
            catch (Exception ex)
            {
                // ignore token refresh error
                _logger.LogDebug("Encounter exception when getting refreshed token. Ignore the error: " + ex.Message);
            }
            return(accessToken); // still pass eixsting token to SDK if refresh failed
        }
Beispiel #15
0
        private IHttpActionResult DoGetDetail(QueryRequest request, string tryGetToken)
        {
            string directoryName         = AzureADAppConstants.TenantName;
            string clientId              = AzureADAppConstants.ClientId;
            var    credentials           = new UserAssertion(tryGetToken);
            var    authenticationContext = new AuthenticationContext(AzureADGlobalConstants.AuthString + directoryName);
            var    loginResult           = authenticationContext.AcquireTokenAsync(AzureADGlobalConstants.GraphUrl, clientId, credentials)
                                           .Result;

            var token = loginResult.AccessToken;

            var userProfiles = GetUserBy(token, request.Keyword);

            foreach (var profile in userProfiles)
            {
                var photo = GetUserPhoto(token, profile.Id);
                profile.Photo = photo;
            }

            return(Ok(new QueryResponse()
            {
                IsSuccess = true,
                ErrorMessage = "",
                Data = userProfiles,
            }));
        }
Beispiel #16
0
        public async Task <IActionResult> AcquireToken(string resource)
        {
            if (_authOptions.UseAadB2c)
            {
                return(BadRequest("AAD B2C does not support on-behalf-of flow."));
            }
            try
            {
                var claim = this.HttpContext.User.Claims.First(c => c.Type.Equals("access_token"));
                if (null == claim)
                {
                    return(Ok(string.Empty));
                }

                // Get the access token
                var token         = claim.Value;
                var assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer";

                var    user          = this.HttpContext.User;
                string userName      = user.FindFirstValue(ClaimTypes.Upn) ?? user.FindFirstValue(ClaimTypes.Email);
                var    userAssertion = new UserAssertion(token, assertionType, userName);

                var tokenCache       = new MemoryTokenCache(userName, resource);
                var authContext      = new AuthenticationContext($"https://login.microsoftonline.com/{_authOptions.Tenant}", tokenCache);
                var clientCredential = new ClientCredential(_authOptions.ClientId, _authOptions.ClientSecret);
                var result           = await authContext.AcquireTokenAsync(resource, clientCredential, userAssertion);

                return(Ok(result.AccessToken));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Failed to acquire token.");
                throw;
            }
        }
        private static async Task <GraphServiceClient> getClient(string accessToken)
        {
            try
            {
                var applicationId     = ConfigurationManager.AppSettings["WEBSITE_AUTH_CLIENT_ID"];
                var applicationSecret = ConfigurationManager.AppSettings["WEBSITE_AUTH_CLIENT_SECRET"];
                var tenant            = ConfigurationManager.AppSettings["Tenant"];
                var cac                  = new ClientCredential(applicationId, applicationSecret);
                var ua                   = new UserAssertion(accessToken);
                var authContext          = new AuthenticationContext($"https://login.microsoftonline.com/{tenant}", false);
                var authenticationResult = await authContext.AcquireTokenAsync("https://graph.microsoft.com", cac, ua);

                return(new GraphServiceClient(new DelegateAuthenticationProvider(
                                                  async(requestMessage) =>
                {
                    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);
                    await Task.FromResult(true);
                }
                                                  )));
            }
            catch (Exception e)
            {
                System.Diagnostics.Trace.TraceError("Error during Graph Authentication: " + e.ToString());
                return(null);
            }
        }
Beispiel #18
0
        public async Task <ActionResult <string> > Get()
        {
            var                   userAccessToken = HttpContext.User.Identities.First().BootstrapContext.ToString();
            var                   claims          = HttpContext.User.Claims;
            string                userName        = claims.Where(m => m.Type == ClaimTypes.Upn).Any() ? claims.First(m => m.Type == ClaimTypes.Upn).Value : claims.First(m => m.Type == ClaimTypes.Email).Value;
            UserAssertion         userAssertion   = new UserAssertion(userAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
            string                userObjectID    = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
            AuthenticationContext authContext     = new AuthenticationContext(AzureAdOptions.Settings.Authority);
            ClientCredential      credential      = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);
            var                   result          = await authContext.AcquireTokenAsync(AzureAdOptions.Settings.ResourceId, credential, userAssertion);

            // Retrieve data from API.
            var handler = new HttpClientHandler();

            handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
            handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
            HttpClient         client  = new HttpClient(handler);
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.APIBaseAddress + "/api/values");

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

            if (response.IsSuccessStatusCode)
            {
                return($"response from API 2 using on behalf of flow is : {response.Content.ReadAsStringAsync().Result}");
            }

            return(null);
        }
Beispiel #19
0
        public async Task <string> GetProposalManagerTokenOnBehalfOfAsync()
        {
            try
            {
                const string siteUrl = "proposalcreation.azurewebsites.net";
                // Get the raw token that the add-in page received from the Office host.
                var bootstrapContext = ((ClaimsIdentity)contextAccessor.HttpContext.User.Identity).BootstrapContext.ToString();

                var userAssertion = new UserAssertion(bootstrapContext, "urn:ietf:params:oauth:grant-type:jwt-bearer");

                // Get the access token for MS Graph.
                var clientCred = new ClientCredential(secret);
                var cca        =
                    new ConfidentialClientApplication(appId,
                                                      $"https://{siteUrl}", clientCred, null, null);

                // The AcquireTokenOnBehalfOfAsync method will first look in the MSAL in memory cache for a
                // matching access token. Only if there isn't one, does it initiate the "on behalf of" flow
                // with the Azure AD V2 endpoint.
                var apiScope = $"api://{proposalManagerApiId}/access_as_user";
                var result   = await cca.AcquireTokenOnBehalfOfAsync(new[] { apiScope }, userAssertion, "https://login.microsoftonline.com/common/oauth2/v2.0");

                return(result.AccessToken);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Get token using client credentials flow
        /// </summary>
        /// <param name="configuration">IConfiguration instance.</param>
        /// <param name="httpClientFactory">IHttpClientFactory instance.</param>
        /// <param name="httpContextAccessor">IHttpContextAccessor instance.</param>
        /// <returns>App access token on behalf of user.</returns>
        public static async Task <string> GetAccessTokenOnBehalfUserAsync(IConfiguration configuration, IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor)
        {
            var tenantId = configuration["AzureAd:TenantId"];
            IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(configuration["AzureAd:MicrosoftAppId"])
                                                 .WithClientSecret(configuration["AzureAd:MicrosoftAppPassword"])
                                                 .WithAuthority($"https://login.microsoftonline.com/{tenantId}")
                                                 .Build();

            try
            {
                var httpContext = httpContextAccessor.HttpContext;
                httpContext.Request.Headers.TryGetValue("Authorization", out StringValues assertion);
                var           idToken = assertion.ToString().Split(" ")[1];
                UserAssertion assert  = new UserAssertion(idToken);
                List <string> scopes  = new List <string>();
                scopes.Add("https://graph.microsoft.com/User.Read");
                var responseToken = await app.AcquireTokenOnBehalfOf(scopes, assert).ExecuteAsync();

                return(responseToken.AccessToken.ToString());
            }
            catch (Exception ex)
            {
                return(ex.Message);
            }
        }
        public async Task <IActionResult> GetGraphAccessTokenAsync()
        {
            try
            {
                ClientCredential clientCred      = new ClientCredential(appKey);
                string           userAccessToken = ((ClaimsIdentity)HttpContext.User.Identity).BootstrapContext.ToString();
                UserAssertion    userAssertion   = new UserAssertion(userAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer");


                const string siteUrl = "smartlink.azurewebsites.net";

                ConfidentialClientApplication cca =
                    new ConfidentialClientApplication(clientId,
                                                      $"https://{siteUrl}", clientCred, null, null);


                AuthenticationResult result = await cca.AcquireTokenOnBehalfOfAsync(new[] { resourceId }, userAssertion, "https://login.microsoftonline.com/common/oauth2/v2.0");

                return(Ok(result.AccessToken));
            }
            catch (Exception ex)
            {
                return(BadRequest(ex.Message));
            }
        }
        static void Main(string[] args)
        {
            string[] scopes      = { "user.read" };
            string   accesstoken = " ";
            string   authority   = "https://login.microsoftonline.com/<your tenat name>/oauth2/v2.0/token";
            string   appKey      = "";
            string   clientId    = "";

            var app = ConfidentialClientApplicationBuilder.Create(clientId)
                      .WithAuthority(authority)
                      .WithClientSecret(appKey)
                      .Build();
            UserAssertion userAssertion = new UserAssertion(accesstoken, "urn:ietf:params:oauth:grant-type:jwt-bearer");
            var           result        = app.AcquireTokenOnBehalfOf(scopes, userAssertion).ExecuteAsync().Result;

            string             requestUrl = "https://graph.microsoft.com/v1.0/me";
            HttpClient         client     = new HttpClient();
            HttpRequestMessage request    = new HttpRequestMessage(HttpMethod.Get, requestUrl);

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

            if (response.IsSuccessStatusCode)
            {
                string responseString = response.Content.ReadAsStringAsync().Result;
                var    profile        = JsonConvert.DeserializeObject <JObject>(responseString);
                Console.WriteLine(profile);
                Console.ReadLine();
            }
        }
        private static async Task <string> GetSharePointAccessTokenForUser(string webServerRelativeUrl, string incomingAccessToken)
        {
            /***
             * SEE https://www.vrdmn.com/2018/05/spfx-calling-back-to-sharepoint-from.html
             *
             */
            //Exchange the SPFx access token with another Access token containing the delegated scope for Microsoft Graph
            ClientCredential clientCred    = new ClientCredential(ConfigurationManager.AppSettings["ClientId"], ConfigurationManager.AppSettings["ClientSecret"]);
            UserAssertion    userAssertion = new UserAssertion(incomingAccessToken);

            string authority   = $"https://login.microsoftonline.com/{ConfigurationManager.AppSettings["TenantId"]}";
            var    authContext = new AuthenticationContext(authority);
            AuthenticationResult authResult;
            string spRootResourceUrl = $"https://{ConfigurationManager.AppSettings["HostName"]}";

            try
            {
                authResult = await authContext.AcquireTokenAsync(spRootResourceUrl, clientCred, userAssertion);
            }
            catch (Exception ex)
            {
                throw new Exception("An error occurred aquiring the SharePoint access token. Please ensure that the client ID and client secret of the App Registration have been added to the ClientID and ClientSecrest settings on this Azure function.");
            }

            return(authResult.AccessToken);
        }
        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            var httpContext = _httpContextAccessor.HttpContext;

            //Get the access token used to call this API
            string token = await httpContext.GetTokenAsync("access_token");

            //We are passing an *assertion* to Azure AD about the current user
            //Here we specify that assertion's type, that is a JWT Bearer token
            string assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer";

            //User name is needed here only for ADAL, it is not passed to AAD
            //ADAL uses it to find a token in the cache if available
            var    user     = httpContext.User;
            string userName = user.FindFirstValue(ClaimTypes.Upn) ?? user.FindFirstValue(ClaimTypes.Email);

            var userAssertion = new UserAssertion(token, assertionType, userName);

            //Construct the token cache
            var cache = new DistributedTokenCache(user, _distributedCache, _loggerFactory, _dataProtectionProvider);

            var authContext      = new AuthenticationContext(_authSettings.Authority, cache);
            var clientCredential = new ClientCredential(_authSettings.ClientId, _authSettings.ClientSecret);
            //Acquire access token
            var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion);

            //Set the authentication header
            request.Headers.Authorization = new AuthenticationHeaderValue(result.AccessTokenType, result.AccessToken);
        }
        public async Task AcquireTokenByOboAccessTokenExpiredRefreshTokenAvailableAsync()
        {
            using (var httpManager = new MockHttpManager())
            {
                httpManager.AddInstanceDiscoveryMockHandler();

                AddMockHandlerAadSuccess(httpManager, TestConstants.AuthorityCommonTenant);

                var cca = ConfidentialClientApplicationBuilder
                          .Create(TestConstants.ClientId)
                          .WithClientSecret(TestConstants.ClientSecret)
                          .WithAuthority(TestConstants.AuthorityCommonTenant)
                          .WithHttpManager(httpManager)
                          .BuildConcrete();

                UserAssertion userAssertion = new UserAssertion(TestConstants.DefaultAccessToken);
                var           result        = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);

                //Expire access tokens
                TokenCacheHelper.ExpireAccessTokens(cca.UserTokenCacheInternal);

                MockHttpMessageHandler mockTokenRequestHttpHandlerRefresh = AddMockHandlerAadSuccess(httpManager, TestConstants.AuthorityCommonTenant);
                mockTokenRequestHttpHandlerRefresh.ExpectedPostData = new Dictionary <string, string> {
                    { "grant_type", "refresh_token" }
                };

                result = await cca.AcquireTokenOnBehalfOf(TestConstants.s_scope, userAssertion).ExecuteAsync().ConfigureAwait(false);

                Assert.IsNotNull(result);
                Assert.AreEqual("some-access-token", result.AccessToken);
            }
        }
Beispiel #26
0
        /// <summary>
        /// Adds an account to the token cache from a JWT token and other parameters related to the token cache implementation
        /// </summary>
        private void AddAccountToCacheFromJwt(IEnumerable <string> scopes, JwtSecurityToken jwtToken, ClaimsPrincipal principal, HttpContext httpContext)
        {
            try
            {
                UserAssertion        userAssertion;
                IEnumerable <string> requestedScopes;
                if (jwtToken != null)
                {
                    userAssertion   = new UserAssertion(jwtToken.RawData, "urn:ietf:params:oauth:grant-type:jwt-bearer");
                    requestedScopes = scopes ?? jwtToken.Audiences.Select(a => $"{a}/.default");
                }
                else
                {
                    throw new ArgumentOutOfRangeException("tokenValidationContext.SecurityToken should be a JWT Token");
                    // TODO: Understand if we could support other kind of client assertions (SAML);
                }

                var application = BuildConfidentialClientApplication(httpContext, principal);

                // .Result to make sure that the cache is filled-in before the controller tries to get access tokens
                var result = application.AcquireTokenOnBehalfOf(requestedScopes.Except(scopesRequestedByMsalNet), userAssertion)
                             .ExecuteAsync()
                             .GetAwaiter().GetResult();
            }
            catch (MsalException ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
        }
        // 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)
        {
            if (_userTokenCache == null)
            {
                _userTokenCache = new SessionTokenCache(userId, _memoryCache).GetCacheInstance();
            }

            var cca = new ConfidentialClientApplication(
                _clientId,
                _redirectUri,
                _credential,
                _userTokenCache,
                null);

            var originalToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");

            var userAssertion = new UserAssertion(originalToken,
                                                  "urn:ietf:params:oauth:grant-type:jwt-bearer");

            try
            {
                var result = await cca.AcquireTokenOnBehalfOfAsync(_scopes, userAssertion);

                return(result.AccessToken);
            }
            catch (Exception ex)
            {
                // Unable to retrieve the access token silently.
                throw new ServiceException(new Error
                {
                    Code    = GraphErrorCode.AuthenticationFailure.ToString(),
                    Message = $"Caller needs to authenticate. Unable to retrieve the access token silently. error: {ex}"
                });
            }
        }
Beispiel #28
0
        /// <summary>
        /// This helper method will get token access form the Azure Active Directory for the
        /// resource application that is being passed as a parameter.
        /// </summary>
        /// <returns>Access Token for the web api service</returns>
        private async Task <string> GetTokenForResource(string resourceUrl)
        {
            try
            {
                string           clientId    = generalSettings.ClientId;
                string           appKey      = generalSettings.AppKey;
                string           aadInstance = generalSettings.AADInstance;
                string           tenant      = generalSettings.Tenant;
                string           resource    = resourceUrl;
                ClientCredential clientCred  = new ClientCredential(clientId, appKey);
                string           accessToken = Context.Request.Headers["Authorization"].ToString().Split(' ')[1];
                //Error JWT Bearer Token? Changeed Code (updated signature)
                UserAssertion userAssertion = new UserAssertion(accessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer"); //Swapped
                //UserAssertion userAssertion = new UserAssertion(accessToken); //Original Code
                string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
                //ToDo: Set the TokenCache to null. Need to implement custom token cache to support multiple users
                //If we dont have the custom cache, there will be some performance overhead.
                AuthenticationContext authContext = new AuthenticationContext(authority, null);
                AuthenticationResult  result      = await authContext.AcquireTokenAsync(resource, clientCred, userAssertion);

                return(result.AccessToken);
            }
            catch (AggregateException ex)
            {
                throw;
            }
            catch (Exception ex)
            {
                customLogger.LogError(ex, MethodBase.GetCurrentMethod().DeclaringType.Name, MethodBase.GetCurrentMethod().Name, logTables.SPOLogTable);
                throw;
            }
        }
Beispiel #29
0
        public async Task UsernamePasswordProvider_ShouldGetAccessTokenForRequestIAccount()
        {
            UserAssertion      assertion          = new UserAssertion("access_token");
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.org/foo");

            httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), new GraphRequestContext
            {
                MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new MsalAuthenticationProviderOption
                            {
                                UserAssertion = assertion,
                                UserAccount   = _graphUserAccount
                            }
                        }
                    }
                }
            });

            AuthenticationResult newAuthResult = MockAuthResult.GetAuthenticationResult();

            _mockClientApplicationBase.Setup((pca) => pca.AcquireTokenByUsernamePasswordAsync(_scopes, string.Empty, It.IsAny <SecureString>()))
            .ReturnsAsync(newAuthResult);

            UsernamePasswordProvider authProvider = new UsernamePasswordProvider(_mockClientApplicationBase.Object, _scopes);
            await authProvider.AuthenticateRequestAsync(httpRequestMessage);

            Assert.IsInstanceOfType(authProvider.ClientApplication, typeof(IPublicClientApplication), "Unexpected client application set.");
            Assert.IsNotNull(httpRequestMessage.Headers.Authorization, "Unexpected auhtorization header set.");
            Assert.AreEqual(_silentAuthResult.AccessToken, httpRequestMessage.Headers.Authorization.Parameter, "Unexpected access token set.");
        }
        public void OBOUserAssertionHashUsernamePassedTest()
        {
            TokenCache    cache         = TokenCacheHelper.CreateCacheWithItems();
            string        someAssertion = "some-assertion-passed-by-developer";
            TokenCacheKey key           = cache.tokenCacheDictionary.Keys.First();

            //update cache entry with hash of an assertion that will not match
            cache.tokenCacheDictionary[key].UserAssertionHash =
                new CryptographyHelper().CreateSha256Hash(someAssertion);

            ConfidentialClientApplication app = new ConfidentialClientApplication(TestConstants.DefaultClientId,
                                                                                  TestConstants.DefaultRedirectUri, new ClientCredential(TestConstants.DefaultClientSecret), new TokenCache());

            app.UserTokenCache = cache;

            //this is a fail safe. No call should go on network
            HttpMessageHandlerFactory.MockHandler = new MockHttpMessageHandler()
            {
                Method          = HttpMethod.Post,
                ResponseMessage =
                    MockHelpers.CreateInvalidGrantTokenResponseMessage()
            };

            UserAssertion assertion          = new UserAssertion(someAssertion, AssertionType, key.DisplayableId);
            Task <AuthenticationResult> task = app.AcquireTokenOnBehalfOfAsync(key.Scope.AsArray(),
                                                                               assertion, key.Authority, TestConstants.DefaultPolicy);
            AuthenticationResult result = task.Result;

            Assert.IsNotNull(result);
            Assert.AreEqual(key.UniqueId, result.User.UniqueId);
            Assert.AreEqual(key.DisplayableId, result.User.DisplayableId);
            Assert.AreEqual(HashAccessToken,
                            cache.tokenCacheDictionary[key].UserAssertionHash);
        }
        public OnBehalfOfRequest(AuthenticationRequestParameters authenticationRequestParameters, UserAssertion userAssertion)
            : base(authenticationRequestParameters)
        {
            if (userAssertion == null)
            {
                throw new ArgumentNullException("userAssertion");
            }

            this.userAssertion = userAssertion;
            this.User = new User { DisplayableId = userAssertion.UserName };
            this.assertionHash = PlatformPlugin.CryptographyHelper.CreateSha256Hash(userAssertion.Assertion);
            this.SupportADFS = false;
        }
        public SilentWebUiRequest(AuthenticationRequestParameters authenticationRequestParameters, UserAssertion userAssertion)
            : base(authenticationRequestParameters)
        {
            if (userAssertion == null)
            {
                throw new ArgumentNullException("userAssertion");
            }

            if (string.IsNullOrWhiteSpace(userAssertion.AssertionType))
            {
                throw new ArgumentException(MsalErrorMessage.UserCredentialAssertionTypeEmpty, "userAssertion");
            }

            this.userAssertion = userAssertion;
        }
        internal override async Task PreTokenRequest()
        {
            await base.PreTokenRequest().ConfigureAwait(false);
            if (this.PerformUserRealmDiscovery())
            {
                UserRealmDiscoveryResponse userRealmResponse = await UserRealmDiscoveryResponse.CreateByDiscoveryAsync(this.Authenticator.UserRealmUri, this.userCredential.UserName, this.CallState).ConfigureAwait(false);
                PlatformPlugin.Logger.Information(this.CallState, string.Format("User with hash '{0}' detected as '{1}'", PlatformPlugin.CryptographyHelper.CreateSha256Hash(this.userCredential.UserName), userRealmResponse.AccountType));

                if (string.Compare(userRealmResponse.AccountType, "federated", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (string.IsNullOrWhiteSpace(userRealmResponse.FederationMetadataUrl))
                    {
                        throw new MsalException(MsalError.MissingFederationMetadataUrl);
                    }

                    WsTrustAddress wsTrustAddress = await MexParser.FetchWsTrustAddressFromMexAsync(userRealmResponse.FederationMetadataUrl, this.userCredential.UserAuthType, this.CallState).ConfigureAwait(false);
                    PlatformPlugin.Logger.Information(this.CallState, string.Format("WS-Trust endpoint '{0}' fetched from MEX at '{1}'", wsTrustAddress.Uri, userRealmResponse.FederationMetadataUrl));

                    WsTrustResponse wsTrustResponse = await WsTrustRequest.SendRequestAsync(wsTrustAddress, this.userCredential, this.CallState).ConfigureAwait(false);
                    PlatformPlugin.Logger.Information(this.CallState, string.Format("Token of type '{0}' acquired from WS-Trust endpoint", wsTrustResponse.TokenType));

                    // We assume that if the response token type is not SAML 1.1, it is SAML 2
                    this.userAssertion = new UserAssertion(wsTrustResponse.Token, (wsTrustResponse.TokenType == WsTrustResponse.Saml1Assertion) ? OAuthGrantType.Saml11Bearer : OAuthGrantType.Saml20Bearer, this.userCredential.UserName);
                }
                else
                {
                    throw new MsalException(MsalError.UnsupportedUserType);
                }
            }
        }