i'm developing a netCore API where i have to authenticate applications with a token. Client provide me the token and my API validate it from Keycloak. Everything is Ok, the problem is where i build my app in a Docker Container. Where the token is from an external application this is invalid, but if i personally get the token from keycloak then is valid.
I think maybe is timezone, but i tried to change the timezone of my PC and get the token with postman but is not valid too.
`var client1 = new HttpClient(clientHandler);
var request1 = new HttpRequestMessage();
request1.RequestUri = new Uri(conf["VALIDATION"]);
request1.Method = HttpMethod.Get;
var a = JObject.Parse(result);
Console.WriteLine("access_token=> "+ a.GetValue("access_token").Value<string>());
request1.Headers.Add("Authorization", "Bearer "+token);
var formList1 = new List<KeyValuePair<string, string>>();
request1.Content = new FormUrlEncodedContent(formList1);
var response1 = await client1.SendAsync(request1);
var result1 = await response1.Content.ReadAsStringAsync();
Console.WriteLine(result1);`
the result is:
{"error":"invalid_token","error_description":"Token verification failed"}
Related
I have to get the contacts from Exchange server from any account, so we have used the code from below link.
https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
But it is not working for personal accounts, which is working fine for our organization account. So I have used AadAuthorityAudience property instead of TenantId and changed the scope from EWS.AccessAsUser.All to others. Now authentication got success but getting "The given token is invalid" error while using the token in ExchangeService.
var pcaOptions = new PublicClientApplicationOptions {
ClientId = "77xxxxxxxxxxx92324",
//TenantId = "7887xxxxxxxxxxxxx14",
RedirectUri = "https://login.live.com/oauth20_desktop.srf",
AadAuthorityAudience = AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount};
var pca = PublicClientApplicationBuilder.CreateWithApplicationOptions(pcaOptions).Build();
//var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };
var ewsScopes = new string[] { "User.Read", "Contacts.ReadWrite.Shared" };
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
//ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "araj#concord.net");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
// Make an EWS call
var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
What am doing wrong here?
https://outlook.office365.com/EWS.AccessAsUser.All is the right scope to use. The scope is invalid for personal accounts since they're not supported by EWS.
Sorry for the multiple post about the same issue!
I'm trying to upload a self signed sertificate to application manifest created on Microsoft Registration Portal but I have some issues which I don't completly understand why, According to this answer, it's very much possible to upload the certificate using DELEGATED PERMISSIONS however I don't see the reason why I can't use Application Permissions since I only need the AccessToken and I get that with the client_credential grant flow,
Below is the code that I have tried but when retrieving the token with client_credential grant flow, I get stuck att var application = activeDirectoryClient.Applications["ApplicationObjectId"].ExecuteAsync().Result;
and when trying to use the code given to my by Tom Sung in the previous post, the applications exits with error "must have client_credentil or client_assertion in request body"
this is the code that I have tried:
private static async Task<string> GetAppTokenAsync(string graphResourceId, string tenantId, string clientId, string userId)
{
string aadInstance = "https://login.microsoftonline.com/" + tenantId + "/oauth2/token";
var clientCredential = new ClientCredential(clientId, clientSecret);
AuthenticationContext authenticationContextt =
new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}/oauth2/token");
AuthenticationResult result =
await authenticationContextt.AcquireTokenAsync(graphResourceId,
clientCredential);
//token is acquiered and gets stuck
var e = result.AccessToken;
//Tom Suns code
IPlatformParameters parameters = new PlatformParameters(PromptBehavior.SelectAccount);
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance);
var authenticationResult = await authenticationContext.AcquireTokenAsync(graphResourceId, clientId, new Uri("http://localhost"), parameters, new UserIdentifier(userId, UserIdentifierType.UniqueId));
//exits with error
return authenticationResult.AccessToken;
}
try
{
var graphResourceId = "https://graph.windows.net";
var userId = "****";
//used to test if token is acquired
//var tokennn = await GetAppTokenAsync(graphResourceId, tenantID, ClientId, userId);
var servicePointUri = new Uri(graphResourceId);
var serviceRoot = new Uri(servicePointUri, tenant);
var activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await GetAppTokenAsync(graphResourceId, tenantID, ClientId, userId));
AsymmetricKeyParameter myCAprivateKey = null;
//generate a root CA cert and obtain the privateKey
X509Certificate2 MyRootCAcert = CreateCertificateAuthorityCertificate("CN=OutlookIntegration", out myCAprivateKey);
//add CA cert to store
addCertToStore(MyRootCAcert, StoreName.Root, StoreLocation.LocalMachine);
var expirationDate = DateTime.Parse(MyRootCAcert.GetExpirationDateString()).ToUniversalTime();
var startDate = DateTime.Parse(MyRootCAcert.GetEffectiveDateString()).ToUniversalTime();
var binCert = MyRootCAcert.GetRawCertData();
var keyCredential = new KeyCredential
{
CustomKeyIdentifier = MyRootCAcert.GetCertHash(),
EndDate = expirationDate,
KeyId = Guid.NewGuid(),
StartDate = startDate,
Type = "AsymmetricX509Cert",
Usage = "Verify",
Value = binCert
};
//gets stuck here when using clientsecret grant type
var application = activeDirectoryClient.Applications["ApplicationObjectId"].ExecuteAsync().Result;
application.KeyCredentials.Add(keyCredential);
application.UpdateAsync().Wait();
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
I am now completly stuck, Anyone have any idea why it doesn't work with Application Permissions or why it gets stuck at var application = activeDirectoryClient.Applications["ApplicationObjectId"].ExecuteAsync().Result;
Edit 1
is it because I have my app as a web app/API that uses username and password to authenticate?
Based on my test if we want to change the keyCredential, DELEGATED PERMISSIONS is required.
If we want to update Azure AD application other properties, we could use Application Permissions.
Reference:
Azure Active Directory developer glossary
"Delegated" permissions, which specify scope-based access using delegated authorization from the signed-in resource owner, are presented to the resource at run-time as "scp" claims in the client's access token.
"Application" permissions, which specify role-based access using the client application's credentials/identity, are presented to the resource at run-time as "roles" claims in the client's access token.
I have an mvc 5 application with an web api 2. (.NET 4.6)
I implemented the oauth2 configuration next to the authentication for my mvc app (app.UseCookieAuthentication) :
OAuthAuthorizationServerOptions OAuthServerOptions = new
OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
Provider = new AspNetIdentityOAuthAuthorizationServerProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(1000),
};
app.UseOAuthBearerTokens(OAuthServerOptions);
My apis are protected with the Authorize Attribute (global filter).
I use the client credentials grant
I followed these two articles (that are the same)
https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/individual-accounts-in-web-api
https://mitchelsellers.com/blogs/2017/05/10/adding-webapi-oauth-authentication-to-an-existing-project
I'm able to get a token for my user, but when I want to use the token to access my Api, I get a 403 forbidden error
HttpClient client = new HttpClient();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("grant_type", "client_credentials");
parameters.Add("client_id", "4rclFahG7gho8erzbsmTbw==");
parameters.Add("client_secret", "IBSqiYb0kT/lzV0gpQsPxkUDI9ztu0dhHWDe4VQDzKGYm2pl+75sMVfEsoGo4FAxFm0qZUFcDrVMrfqYhn2bzw==");
var content = new FormUrlEncodedContent(parameters);
try
{
HttpResponseMessage result = client.PostAsync("http://localhost:49594/oauth/token", content).Result;
string jsonResult = result.Content.ReadAsStringAsync().Result;
var resultObject = JsonConvert.DeserializeObject<TokenResult>(jsonResult);
var accessToken = resultObject.access_token;
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
result = client.GetAsync("http://localhost:49594/api/v1/echo?id=myt
estvalue").Result;
// RESULT is 403 - Forbidden
I tested with postman as well, and the result is the same.
did anyone experienced the same problem ?
do you know what I' missing ?
Update :
It's working if I deploy my application on a server (azure app services) but still not on my machine
I found the reason of my issue !
I'm using stuntman (https://rimdev.io/stuntman/) for my dev and I forgot to configure it for oauth ...
This line was missing :
StuntmanOptions.AllowBearerTokenPassthrough = true;
I'm trying to achieve "Service Integration Authentication" following the steps here docusign docs and it's doing fine until Requesting the Access Token, where you send the jwt token (which is well formed)
I'm always getting "invalid_grant", and according to that doc, is because some of the claims are invalid. Is there another cause for that error?
All the claims looks good
C#:
//request access token
var client3 = new RestClient("https://" + _host);
var request3 = new RestRequest("/oauth/token", Method.POST);
request3.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request3.AddParameter("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
var headers = new[]
{
new Claim("alg", "RS256"),
new Claim("typ", "JWT"),
}.ToList();
var claims = new[] {
new Claim("iss", _integrationKey), //<-- integration key
new Claim("sub", OAuthGrant.Sub), //<-- returned from /oauth/userinfo (OK)
new Claim("iat", ToUnixTime(DateTime.Now).ToString(), ClaimValueTypes.Integer64),
new Claim("exp", ToUnixTime(DateTime.Now.AddHours(1)).ToString(), ClaimValueTypes.Integer64),
new Claim("aud", _host), //<-- "account-d.docusign.com"
new Claim("scope", "signature"),
}.ToList();
//build jwt from private key. token decodes just fine from https://jwt.io/
var jwtToken = CreateToken(claims, headers, "private-key.pem", Server.MapPath("/"));
request3.AddParameter("assertion", jwtToken);
System.Diagnostics.Debug.WriteLine("jwtToken:" + jwtToken);
var response = client3.Execute<OAuthToken>(request3);
System.Diagnostics.Debug.WriteLine("response content:" + response.Content); //<-- getting "invalid_grant"
return response.Data;
The jwt token was validated using https://jwt.io/ and decodes just fine.
Is docusign demo sandbox
Thanks in advance
daniel
My assumption is the library which you are using is generating wrong assertion for you. You can check DS SDK as well - ConfigureJwtAuthorizationFlow method in DS SDK, it will help you in generating the Assertion in correct way as expected by DS APIs.
I'm trying to get an AppOnly access token for use in the Authorization Bearer header of my request to a REST endpoint in Project Online (SharePoint). Following is a snippet of the code that I was using to retrieve the access token.
private OAuth2AccessTokenResponse GetAccessTokenResponse()
{
var realm = TokenHelper.GetRealmFromTargetUrl([[our_site_url]]);
var resource = $"00000003-0000-0ff1-ce00-000000000000/[[our_site_authority]]#{realm}";
var formattedClientId = $"{ClientId}#{realm}";
var oauth2Request = OAuth2MessageFactory.CreateAccessTokenRequestWithClientCredentials(
formattedClientId,
ClientSecret,
resource);
oauth2Request.Resource = resource;
try
{
var client = new OAuth2S2SClient();
var stsUrl = TokenHelper.AcsMetadataParser.GetStsUrl(realm);
var response = client.Issue(stsUrl, oauth2Request) as OAuth2AccessTokenResponse;
var accessToken = response.AccessToken;
}
catch (WebException wex)
{
using (var sr = new StreamReader(wex.Response.GetResponseStream()))
{
var responseText = sr.ReadToEnd();
throw new WebException(wex.Message + " - " + responseText, wex);
}
}
}
I keep getting 403 Forbidden as the response from the server, even if I include site collection admin credentials with my request. Does anyone out there have any ideas?
After creating a support ticket with Microsoft to figure this out we eventually decided to move away from using app permissions for console application authorization.
Our workaround was to create SharePointOnlineCredentials object using a service account, and then get the Auth cookie from the credentials object to pass with our WebRequest. This solution came from scripts found here: https://github.com/OfficeDev/Project-REST-Basic-Operations