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); }
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)); }
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")); }
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); }
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")); }
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); }
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"); } }
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")); }
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 })); }
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()); }
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); }
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); }
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()); }
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()); }
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); }
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); }
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); }
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")); }
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); }
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")); }
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)); }