Exemplo n.º 1
0
        public async Task PostToken_AuthCodeGrantWithAuthorizationCodeAndSsoTokenNotBelongsToSameUser_Return403()
        {
            // Arrange
            var clientId = _configuration[ConfigurationName.ClientId];
            var scope    = $"{_settings.ApiAppIdUri}/{clientId}/{_settings.Scope}";
            var ssoTokenFromAnotherAuthorizedUser = await Utilities.GetUserAccessToken(_settings.TestUsername2, _settings.TestPassword2, clientId,
                                                                                       _configuration[ConfigurationName.ClientSecret], _configuration[ConfigurationName.OAuthAuthority], scope).ConfigureAwait(false);

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoTokenFromAnotherAuthorizedUser); // sso token belongs to authorized test user 2.

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope         = DefaultGraphScope,
                redirect_uri  = _settings.RedirectUri,
                grant_type    = AadGrantType.AuthorizationCode,
                code          = Utilities.GetAuthorizationCode(_settings, _configuration), // authorization code belongs to authorized test user 1.
                code_verifier = _settings.CodeVerifier
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Forbidden, result.Response.StatusCode);
        }
Exemplo n.º 2
0
        private async Task <IActionResult> AuthCodeFlow(PostTokenRequestBody body)
        {
            var scopes = body.scope.Split(' ');

            if (!scopes.Contains(CommonScope.OfflineAccess))
            {
                scopes.Append(CommonScope.OfflineAccess);
            }

            var ssoToken = GetJwtBearerTokenFromRequest();
            var token    = await _authHandler.AcquireTokenByAuthorizationCode(
                scopes,
                body.redirect_uri,
                body.code,
                body.code_verifier,
                ssoToken)
                           .ConfigureAwait(false);

            var result = new PostTokenResponse()
            {
                access_token = token.AccessToken,
                scope        = string.Join(' ', token.Scopes),
                expires_on   = token.ExpiresOn
            };

            return(Ok(result));
        }
Exemplo n.º 3
0
        public async Task PostToken_AuthCodeGrantWithIncorrectCodeVerifier_Return400()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope         = DefaultGraphScope,
                redirect_uri  = _settings.RedirectUri,
                grant_type    = PostTokenGrantType.AuthorizationCode,
                code          = Utilities.GetAuthorizationCode(_settings, _configuration),
                code_verifier = _settings.CodeVerifier + "incorrect_value"
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.BadRequest, result.Response.StatusCode);
            Assert.AreEqual("application/problem+json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.AreEqual((int)HttpStatusCode.BadRequest, result.Body.Status);
            Assert.AreEqual(ExpectedProblemType.AadUiRequiredException, result.Body.Type);
            Assert.IsTrue(result.Body.Detail.Contains("The Code_Verifier does not match the code_challenge supplied in the authorization request"));
        }
Exemplo n.º 4
0
        public async Task PostToken_SsoGrantWithInvalidClientSecretInApiSetting_Return500()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var customizedAppConfiguration = new Dictionary <string, string>(_defaultConfigurations);

            customizedAppConfiguration[ConfigurationName.ClientSecret] = Guid.NewGuid().ToString();
            var factory = _aadInstance.ConfigureWebApplicationFactory(customizedAppConfiguration);
            var client  = factory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.InternalServerError, result.Response.StatusCode);
            Assert.AreEqual("application/problem+json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.AreEqual((int)HttpStatusCode.InternalServerError, result.Body.Status);
            Assert.AreEqual(ExpectedProblemType.AuthInternalServerException, result.Body.Type);
            Assert.AreEqual("The AAD configuration in server is invalid.", result.Body.Detail);
        }
Exemplo n.º 5
0
        public async Task PostToken_AuthCodeGrantWithInvalidScope_Return400()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);
            var Code = Utilities.GetAuthorizationCode(_settings, _configuration);

            Assert.NotNull(Code);
            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope         = "https://storage.azure.com/.default",
                redirect_uri  = _settings.RedirectUri,
                grant_type    = PostTokenGrantType.AuthorizationCode,
                code          = Utilities.GetAuthorizationCode(_settings, _configuration),
                code_verifier = _settings.CodeVerifier
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.BadRequest, result.Response.StatusCode);
            Assert.AreEqual("application/problem+json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.AreEqual((int)HttpStatusCode.BadRequest, result.Body.Status);
            Assert.AreEqual(ExpectedProblemType.AadClientException, result.Body.Type);
            Assert.IsTrue(result.Body.Detail.Contains("AADSTS65005"));
        }
Exemplo n.º 6
0
        public async Task PostToken_AuthorizationTokenClientNotAllowed_Return403()
        {
            var scope = $"{_settings.ApiAppIdUri}/{_settings.AdminClientId}/{_settings.Scope}";
            // Arrange
            var tokenFromUnauthorizedClient = await Utilities.GetUserAccessToken(_settings.TestUsername, _settings.TestPassword, _settings.AdminClientId, _settings.AdminClientSecret,
                                                                                 _configuration[ConfigurationName.OAuthAuthority], scope).ConfigureAwait(false);

            // Temporary workaround the consent for new AAD app in each test run
            // TODO: Add UI automation to grant consent for new AAD app in each test run
            var customizedAppConfiguration = new Dictionary <string, string>(_defaultConfigurations);

            customizedAppConfiguration[ConfigurationName.IdentifierUri] = $"{_settings.AdminClientId}";
            var factory = _aadInstance.ConfigureWebApplicationFactory(customizedAppConfiguration);
            var client  = factory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenFromUnauthorizedClient);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Forbidden, result.Response.StatusCode);
        }
Exemplo n.º 7
0
        public async Task <IActionResult> PostToken([FromBody] PostTokenRequestBody body)
        {
            _logger.LogDebug($"New request to token endpoint. Simple Auth version:{GlobalConfig.SimpleAuthVersion}."
                             + $"Body:{JsonConvert.SerializeObject(body)}. Headers:{JsonConvert.SerializeObject(Request.Headers)}");

            if (string.IsNullOrEmpty(body.scope))
            {
                throw new InvalidModelException("scope is required in request body");
            }

            switch (body.grant_type)
            {
            case GrantType.AuthorizationCode:
                return(await AuthCodeFlow(body).ConfigureAwait(false));

            case GrantType.SsoToken:
                return(await AcquireAccessTokenBySsoToken(body).ConfigureAwait(false));

            case null:
                throw new InvalidModelException("grant_type is required in request body");

            default:
                throw new InvalidModelException($"grant_type {body.grant_type} is not supported");
            }
        }
Exemplo n.º 8
0
        public async Task PostToken_WithExpiredAuthorizationToken_Return401()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            await Task.Delay(TimeSpan.FromSeconds(15 * 60 + 20)).ConfigureAwait(false);

            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Unauthorized, result.Response.StatusCode);
            Assert.IsNull(result.Body);
            Assert.IsTrue(result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault().Contains("Bearer"));
            Assert.IsTrue(result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault().Contains("error=\"invalid_token\""));
            Assert.IsTrue(result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault().Contains("The token expired"));
        }
Exemplo n.º 9
0
        private async Task <IActionResult> AcquireAccessTokenBySsoToken(PostTokenRequestBody body)
        {
            string[] scopes   = body.scope.Split(' ');
            var      ssoToken = GetJwtBearerTokenFromRequest();

            // Do not get from cache temporary due to MSAL scope matching issue when cached token contains .default scope
            //var token = await _authHandler.AcquireTokenBySsoToken(User, ssoToken, scopes).ConfigureAwait(false);

            var token = await _authHandler.AcquireTokenBySsoTokenOnBehalfOf(ssoToken, scopes).ConfigureAwait(false);

            return(Ok(new PostTokenResponse
            {
                access_token = token.AccessToken,
                scope = string.Join(' ', token.Scopes),
                expires_on = token.ExpiresOn
            }));
        }
Exemplo n.º 10
0
        public async Task PostToken_WithNoAuhotirzationToken_Return401()
        {
            // Arrange
            var client = _defaultFactory.CreateDefaultClient();

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Unauthorized, result.Response.StatusCode);
            Assert.IsNull(result.Body);
            Assert.AreEqual("Bearer", result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault());
        }
Exemplo n.º 11
0
        public async Task PostToken_AuthCodeGrantWithCorrectBody_Return200()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient(new RetryHandler(new HttpClientHandler()));

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            HttpResponseWithBody <PostTokenResponse> result = null;
            int maxRetries = 5;

            for (int i = 0; i < maxRetries; i++)
            {
                var requestBody = new PostTokenRequestBody
                {
                    scope         = DefaultGraphScope,
                    redirect_uri  = _settings.RedirectUri,
                    grant_type    = PostTokenGrantType.AuthorizationCode,
                    code          = Utilities.GetAuthorizationCode(_settings, _configuration), // Reusing same auth code will result in error, so cannot use the retry handler
                    code_verifier = _settings.CodeVerifier
                };
                result = await PostToAuthTokenApi <PostTokenResponse>(client, requestBody);

                if (result.Response.IsSuccessStatusCode)
                {
                    break;
                }

                await Task.Delay(1000);
            }

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, result.Response.StatusCode);
            Assert.AreEqual("application/json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.NotNull(result.Body.scope);
            Assert.IsTrue(result.Body.scope.Contains(DefaultGraphScope));
            Assert.AreNotEqual(DateTimeOffset.MinValue, result.Body.expires_on);
            Assert.NotNull(result.Body.access_token);
        }
Exemplo n.º 12
0
        public async Task PostToken_NoAccessAsUserScope_Return403()
        {
            // Arrange
            var scope    = $"{_settings.ApiAppIdUri}/{_configuration[ConfigurationName.ClientId]}/another_scope";
            var ssoToken = await GetUserAccessToken(scope);

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Forbidden, result.Response.StatusCode);
        }
Exemplo n.º 13
0
        public async Task PostToken_WithIncorrectAuthorizationToken_Return401()
        {
            // Arrange
            string ssoToken = "not_a_jwt_token";
            var    client   = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Unauthorized, result.Response.StatusCode);
            Assert.IsNull(result.Body);
            Assert.AreEqual("Bearer error=\"invalid_token\"", result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault());
        }
Exemplo n.º 14
0
        public async Task PostToken_WithIncorrectAudience_Return401() // TODO: confirm the behavior
        {
            // Arrange
            var ssoToken = await GetUserAccessToken(DefaultGraphScope);

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Unauthorized, result.Response.StatusCode);
            Assert.IsNull(result.Body);
            Assert.AreEqual("Bearer error=\"invalid_token\", error_description=\"The signature is invalid\"", result.Response.Headers.GetValues("WWW-Authenticate").FirstOrDefault());
        }
Exemplo n.º 15
0
        public async Task PostToken_WithApplicationToken_Return403()
        {
            // Arrange
            var applicationToken = await Utilities.GetAccessTokenUsingClientCredentialsFlow(_configuration[ConfigurationName.OAuthAuthority],
                                                                                            _teamsAadInfo.AppId, _teamsAadInfo.ClientSecret,
                                                                                            Utilities.GetIdentifierUri(_settings.ApiAppIdUri, _teamsAadInfo.AppId) + "/.default");

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", applicationToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken,
            };
            var result = await PostToAuthTokenApi <string>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.Forbidden, result.Response.StatusCode);
        }
Exemplo n.º 16
0
        public async Task PostToken_GrantTypeNullInBody_Return400()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody()
            {
                grant_type = null,
                scope      = DefaultGraphScope
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.BadRequest, result.Response.StatusCode);
            Assert.AreEqual(ExpectedProblemType.InvalidModelException, result.Body.Type);
            Assert.AreEqual((int)HttpStatusCode.BadRequest, result.Body.Status);
            Assert.AreEqual("grant_type is required in request body", result.Body.Detail);
        }
Exemplo n.º 17
0
        public async Task PostToken_SsoGrantWithNoScopeInBody_Return400()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                grant_type = PostTokenGrantType.SsoToken
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.BadRequest, result.Response.StatusCode);
            Assert.AreEqual("application/problem+json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.AreEqual((int)HttpStatusCode.BadRequest, result.Body.Status);
            Assert.AreEqual(ExpectedProblemType.InvalidModelException, result.Body.Type);
            Assert.AreEqual("scope is required in request body", result.Body.Detail);
        }
Exemplo n.º 18
0
        public async Task PostToken_SsoGrantWithAnotherConsentedScope_Return200WithNewScopeInToken()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient(new RetryHandler(new HttpClientHandler()));

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var firstRequestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken
            };
            var firstResult = await PostToAuthTokenApi <PostTokenResponse>(client, firstRequestBody);

            Assert.AreEqual(HttpStatusCode.OK, firstResult.Response.StatusCode);

            // Consent another permission
            Utilities.ConsentAndGetAuthorizationCode(_settings.AuthorizeUrl, _teamsAadInfo.AppId, _settings.RedirectUri,
                                                     "https://graph.microsoft.com/User.ReadBasic.All", _settings.CodeChallenge, _settings.TestUsername, _settings.TestPassword);

            var secondRequestBody = new PostTokenRequestBody
            {
                scope      = "https://graph.microsoft.com/User.Read User.ReadBasic.All",
                grant_type = PostTokenGrantType.SsoToken
            };
            var secondResult = await PostToAuthTokenApi <PostTokenResponse>(client, secondRequestBody);

            Assert.AreEqual(HttpStatusCode.OK, secondResult.Response.StatusCode);

            // Assert
            Assert.IsTrue(firstResult.Body.scope.ToLowerInvariant().Contains("https://graph.microsoft.com/user.read"));
            Assert.IsFalse(firstResult.Body.scope.ToLowerInvariant().Contains("https://graph.microsoft.com/user.readbasic.all"));
            Assert.IsTrue(secondResult.Body.scope.ToLowerInvariant().Contains("https://graph.microsoft.com/user.readbasic.all"));
        }
Exemplo n.º 19
0
        public async Task PostToken_SsoGrantWithCorrectBody_Return200()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient(new RetryHandler(new HttpClientHandler()));

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = DefaultGraphScope,
                grant_type = PostTokenGrantType.SsoToken
            };
            var result = await PostToAuthTokenApi <PostTokenResponse>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.OK, result.Response.StatusCode);
            Assert.AreEqual("application/json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.IsNotNull(result.Body.access_token);
            Assert.IsTrue(result.Body.scope.Contains(DefaultGraphScope));
            Assert.AreNotEqual(DateTimeOffset.MinValue, result.Body.expires_on);
        }
Exemplo n.º 20
0
        public async Task PostToken_SsoGrantWhenUserNotGrant_Return400()
        {
            // Arrange
            var ssoToken = await GetUserAccessToken();

            var client = _defaultFactory.CreateDefaultClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", ssoToken);

            // Act
            var requestBody = new PostTokenRequestBody
            {
                scope      = "https://graph.microsoft.com/User.Export.All",
                grant_type = PostTokenGrantType.SsoToken
            };
            var result = await PostToAuthTokenApi <ProblemDetails>(client, requestBody);

            // Assert
            Assert.AreEqual(HttpStatusCode.BadRequest, result.Response.StatusCode);
            Assert.AreEqual("application/problem+json; charset=utf-8", result.Response.Content.Headers.ContentType.ToString());
            Assert.AreEqual((int)HttpStatusCode.BadRequest, result.Body.Status);
            Assert.AreEqual(ExpectedProblemType.AadUiRequiredException, result.Body.Type);
            Assert.IsTrue(result.Body.Detail.Contains("AADSTS65001"));
        }
Exemplo n.º 21
0
        private async Task <HttpResponseWithBody <T> > PostToAuthTokenApi <T>(HttpClient client, PostTokenRequestBody body)
        {
            var stringContent = new StringContent(
                JsonConvert.SerializeObject(body, new JsonSerializerSettings {
                NullValueHandling = NullValueHandling.Ignore
            }),
                null, "application/json");

            return(await PostToAuthTokenApi <T>(client, stringContent));
        }