Unable to get long lived expiration token - c#

I use Facebook C# SDK v 6 and enabled "Remove Offline Access" on my application settings
and after login and get the access token, I am trying to exchange for long lived token(60days one)
I am unable to get it as both tokens expiration is with in 24 hrs.
Here is my code
For log in to Facebook
private const string Scope = "publish_stream,manage_pages";
FacebookClient _fb = new FacebookClient();
var fbLoginUrl = _fb.GetLoginUrl(
new
{
client_id = AppId,
client_secret = Appsecret,
redirect_uri = RedirectUri,
response_type = "code",
scope = Scope,
state = state
});
To get short lived access token
if (Request.QueryString["code"] != null)
code = Request.QueryString["code"];
var result = _fb.Post("oauth/access_token",
new
{
client_id = AppId,
client_secret = Appsecret,
redirect_uri = RedirectUri,
code = code,
scope = Scope,
response_type="token"
});
To get long lived access token
var result1 = _fb.Post("oauth/access_token",
new
{
client_id = AppId,
client_secret = Appsecret,
grant_type = "fb_exchange_token",
fb_exchange_token= Session["fb_access_token"] as string
});

This will do.
var result = GetExtendedAccessToken("my_short_lived_old_token");
var extendedToken = result.access_token;
public dynamic GetExtendedAccessToken(string oldToken)
{
dynamic result = new ExpandoObject();
try
{
var api = new FacebookClient
{
AccessToken = oldToken,
AppId = ClientID,
AppSecret = ClientSecret
};
dynamic parameters = new ExpandoObject();
parameters.grant_type = "fb_exchange_token";
parameters.fb_exchange_token = oldToken;
parameters.client_id = ClientID;
parameters.client_secret = ClientSecret;
result = api.Get("oauth/access_token", parameters);
}
catch (FacebookOAuthException err)
{
result.error = "Error";
result.message = err.Message;
}
catch (Exception err)
{
result.error = "Error";
result.message = err.Message;
}
return result;
}

Related

'authority' should be in Uri format Parameter name: authority while getting access token by passing "TenantID"

I am trying to add authentication to api call in Rest sharp version 108.0.2
error : 'authority' should be in Uri format Parameter name: authority
I have upgraded the Restsharp version from 106 to 108 , Then here previously we are using HttpClient but there are some deprecated interfaces in that so i am trying to use RestClient but here i am unable to get below authmechanism.
var response = HttpClient.CallAsync<string>(new HttpClientArgs
{
Uri = new Uri(uri),
Verb = HttpVerb.Put,
HttpAuthMechanism = HttpAuthMechanism.AzureAd,
AzureAdConfig = new AzureAdConfig()
{
ClientId = ClientID,
ClientSecret = ClientSecret,
ResourceId = ResourceID,
TenantId = TenantID
},
Body = JsonConvert.SerializeObject(body)
});
string Authority = String.Format(TenantID);
AuthenticationContext ac = new AuthenticationContext(Authority);
string resourceID = ResourceID;
string clientID = ClientID;
try
{
UserCredential uc = new UserCredential();
Task<AuthenticationResult> task = ac.AcquireTokenAsync(resourceID, clientID, uc);
task.Wait(10000);
AuthenticationResult result = task.Result;
string token = result.AccessToken;
return token;
}
catch (Exception ex)
{
if (ex.InnerException.Message.ToLower().Contains("interactive authorization"))
{
string token = "prompt";
return token;
}
return (ex.Message);
throw ex;
}

MCAS REST API Limit issues(nextQueryFilters)

I am trying to collect Microsoft Defender for Cloud Activity Log using C#.
If you look at the Python example, the value of the nextQueryFilters item should be entered as a filter.
But when I run it in C# and check the test result, the items in nextQueryFilters themselves are not retrieved.
Please check if there is a problem with my code.
string tenantId = "mytenantId";
string appId = "myappId";
string appSecret = "myappSecret";
const string authority = "https://login.microsoftonline.com";
const string MCASResourceId = "myMCASResourceId";
AuthenticationContext auth = new AuthenticationContext($"{authority}/{tenantId}/");
ClientCredential clientCredential = new ClientCredential(appId, appSecret);
AuthenticationResult authenticationResult = auth.AcquireTokenAsync(MCASResourceId, clientCredential).GetAwaiter().GetResult();
string token = authenticationResult.AccessToken;
var httpClient = new HttpClient();
bool hasNextPage = false;
do
{
Url = "https://url.portal.cloudappsecurity.com/api/v1/activities/?filters={\"date\":{ \"gte_ndays\":1}}&isScan:True";
using (var request = new HttpRequestMessage(HttpMethod.Post, Url))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using (HttpResponseMessage respose = httpClient.SendAsync(request).GetAwaiter().GetResult())
{
string json = respose.Content.ReadAsStringAsync().Result;
}
}
} while (hasNextPage);

odic Authentificsation Is wating for connection

Hy I have written an Console Application and i want to connect to the Identity-Server. With the NamedPipeServerStream i want to get Result. However, it always tries to connect to the Server.
Here is my code:
var options = new OidcClientOptions
{
Authority = authority,
ClientId = clientId,
ClientSecret = clientSecret,
Scope = scope,
RedirectUri = redirectUrl,
ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect
};
_oidcClient = new OidcClient(options);
var state = await _oidcClient.PrepareLoginAsync();
var callbackManager = new CallbackManager(state.State);
Process.Start(state.StartUrl);
var response = await callbackManager.RunServer();
var result = await _oidcClient.ProcessResponseAsync(response, state);
Here is my Callbackmanager
public async Task<string> RunServer(CancellationToken? token = null)
{
token = CancellationToken.None;
using (var server = new NamedPipeServerStream(_name, PipeDirection.In))
{
//here it spos and waits for the Connection
await server.WaitForConnectionAsync(token.Value);
using (var sr = new StreamReader(server))
{
var msg = await sr.ReadToEndAsync();
return msg;
}
}
}
the solution was to add an Flow:
Flow = OidcClientOptions.AuthenticationFlow.AuthorizationCode
now it works

PlatformNotSupported Exception when calling AddUserAsync .NET Core 2.0

I am trying to write some code that creates a user in Azure AD using the Graph API. I started w/ an example off the net, but right now it fails when adding the user, on the line
await adClient.Users.AddUserAsync(userGraphObj);
In the CreateUser() method below. The error I get is
I am using .NET Core 2.0, debugging on Windows 7. Googling around and I found that they brought serialization back for 2.0, but only for specific types.
I don't really care. How can I add a user to Azure AD in code?
const String appClientID = "2be733f1-88c3-6482-8e2a-5e9631fc3a32";
const String tenant = "espn.onmicrosoft.com";
const String authString = "https://login.microsoftonline.com/" + tenant;
const String authClientSecret = "dDdaVGee315s65ewDSWEwfdw7wq5efDNO5C3cvN4RA";
const String resAzureGraphAPI = "https://graph.windows.net";
const String serviceRootURL = resAzureGraphAPI + appClientID;
private ActiveDirectoryClient GetAADClient()
{
Uri serviceRoot = new Uri(serviceRootURL);
ActiveDirectoryClient adClient = new ActiveDirectoryClient(
serviceRoot, async () => await GetAppTokenAsync());
return adClient;
}
private static async Task<String> GetAppTokenAsync()
{
AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);
ClientCredential clientCred = new ClientCredential(appClientID, authClientSecret);
AuthenticationResult authResult = await authenticationContext.AcquireTokenAsync(resAzureGraphAPI, clientCred);
return authResult.AccessToken;
}
public async Task<IActionResult> CreateUser()
{
var adClient = GetAADClient();
//Construct The User
String userEmail = "TestUser#example.com";
String mailNickname = userEmail.Split(new char[] { '#' }).FirstOrDefault();
var userGraphObj = new Microsoft.Azure.ActiveDirectory.GraphClient.User()
{
GivenName = "Test",
Surname = "User",
Mobile = "13133124044",
MailNickname = mailNickname,
DisplayName = "Test User",
AccountEnabled = true
};
await adClient.Users.AddUserAsync(userGraphObj);
return Ok(tempPassword);
}
Microsoft itself recommends not to use the Azure AD Graph API anymore, in favor of the Microsoft Graph API (cf blog post).
If you don't have a strong requirement to use the Azure AD API, here are the steps to create a user via the latest API.
Disclaimer :
I never managed to successfully acquire a token from a desktop application
I haven't really understood how the permissions scopes are supposed to be used (here it seems to want a URL, but in the examples it's usually a list of strings, such as User.ReadWrite.All or Directory.ReadWrite.All)
Code to acquire a token:
const String appClientID = "2be733f1-88c3-6482-8e2a-5e9631fc3a32";
const String tenant = "brazzers.onmicrosoft.com";
const String authString = "https://login.microsoftonline.com/" + tenant;
const String authClientSecret = "dDdaVGee315s65ewDSWEwfdw7wq5efDNO5C3cvN4RA";
public static GraphServiceClient GetAuthenticatedClient()
{
var delegateAuthenticationProvider = new DelegateAuthenticationProvider(
async (requestMessage) =>
{
var accessToken = await GetAppTokenAsync();
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
}
);
return new GraphServiceClient(delegateAuthenticationProvider);
}
private static async Task<String> GetAppTokenAsync()
{
// this doesn't work for desktop apps,
// and PublicClientApplication throws a NotImplementedException
var cca = new ConfidentialClientApplication(
appClientID,
authString,
"http://www.example.com/", // no redirect
new ClientCredential(authClientSecret),
new TokenCache(),
new TokenCache());
var authResult = await cca.AcquireTokenForClientAsync(new[] { $"https://graph.microsoft.com/.default" });
return authResult.AccessToken;
}
Code to create a user (courtesy of the samples):
public async Task<User> CreateUser(GraphServiceClient graphClient)
{
// This snippet gets the tenant domain from the Organization object to construct the user's email address.
var organization = await graphClient.Organization.Request().GetAsync();
var domain = organization.CurrentPage[0].VerifiedDomains.ElementAt(0).Name;
// Add the user.
var userEmail = "TestUser#" + domain;
var mailNickname = userEmail.Split(new char[] { '#' }).FirstOrDefault();
return await graphClient.Users.Request().AddAsync(new User
{
AccountEnabled = true,
DisplayName = "Test User",
MailNickname = mailNickname,
PasswordProfile = new PasswordProfile
{
Password = "super_strong_password"
},
UserPrincipalName = userEmail
});
}

What token to be used to generate UserAssertion in AAD in C#

We want to use AcquireTokenAsync to acquire the tokens on behalf of user using the following syntax
public static async Task<UserTokenCache> GetAccessTokens(string userUniqueId)
{
UserTokenCache cache = null;
AuthenticationContext authContext = null;
ClientCredential credential = new ClientCredential(clientId, appKey);
AuthenticationResult powerBIResult = null;
AuthenticationResult graphResult = null;
bool isAdalException = false;
try
{
authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userUniqueId));
powerBIResult = await authContext.AcquireTokenSilentAsync(pbiResourceID, credential, new UserIdentifier(userUniqueId, UserIdentifierType.UniqueId));
graphResult = await authContext.AcquireTokenSilentAsync(graphResourceId, credential, new UserIdentifier(userUniqueId, UserIdentifierType.UniqueId));
cache = new UserTokenCache
{
GraphAccessToken = graphResult.AccessToken,
PBIAccessToken = powerBIResult.AccessToken,
PBITokenExpires = powerBIResult.ExpiresOn,
GraphTokenExpires = graphResult.ExpiresOn
};
}
catch (JsonException je)
{
ExceptionLogger.LogInApplicationInsight(je);
HttpContext.Current.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties(),
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
catch (AdalException ae)
{
ExceptionLogger.LogInApplicationInsight(ae);
if (ae.ErrorCode == "failed_to_acquire_token_silently")
{
isAdalException = true;
}
else
{
HttpContext.Current.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties(),
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
catch (Exception ex)
{
ExceptionLogger.LogInApplicationInsight(ex);
}
if(isAdalException)
{
try
{
string cacheValue = Convert.ToString(cacheManager.get(userUniqueId));
string decryptedCache = CryptographyUtility.Decrypt(cacheValue);
cache = JsonConvert.DeserializeObject<UserTokenCache>(decryptedCache);
UserAssertion pbiAssertion = new UserAssertion(cache.PBIAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", UserProperties.UserName);
UserAssertion graphAssertion = new UserAssertion(cache.GraphAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer", UserProperties.UserName);
cache = null;
powerBIResult = await authContext.AcquireTokenAsync(pbiResourceID, credential, pbiAssertion);
graphResult = await authContext.AcquireTokenAsync(graphResourceId, credential, graphAssertion);
cache = new UserTokenCache
{
GraphAccessToken = graphResult.AccessToken,
PBIAccessToken = powerBIResult.AccessToken,
PBITokenExpires = powerBIResult.ExpiresOn,
GraphTokenExpires = graphResult.ExpiresOn
};
} catch (Exception ex)
{
ExceptionLogger.LogInApplicationInsight(ex);
}
}
return cache;
}
If we use cache.PBIAccessToken and cache.GraphAccessToken to calculate user assertions which are used in AcquireTokenAsync method, it is throwing the error that TenantId is mismatch. In this case, what is the token which needs to be used to calculate UserAssertion.
Generally , we usually use AcquireTokenAsync to get the access token and refresh token the first time user login . After that you could get the token silently(invoke AcquireTokenSilentAsync to get the accessToken ), it will get the token from the TokenCache or silently use refreshToken . If access tokens and refresh tokens both expired ,you may get AdalSilentTokenAcquisitionException( Failed to acquire token silently. Call method AcquireToken) .
Then you could catch that exception , and invokingHttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" },OpenIdConnectAuthenticationDefaults.AuthenticationType); to redirect user to azure ad login page , after login , user call api with AcquireTokenSilentAsync will work since access token/refresh token exist in cache ,and not expired. Your code in if(isAdalException) is useless if i understand your requirement correctly .

Categories

Resources