Is it possible to get a 3-legged auth without user input ?
https://aps.autodesk.com/en/docs/oauth/v2/tutorials/get-3-legged-token/
I have the below code which triggers the web browser to ask for login and press "allow"
button.
I can't run autoamted tasks like this, is there a way to call the API in adeffrent way
in order to pass my credentials and get authorised programmatically ??
public async Task<string> GetCode()
{
var requesturl = $"https://developer.api.autodesk.com/authentication/v1/authorize?response_type=code&client_id={client_id}&redirect_uri={redirecturl}&scope=data:create%20data:read%20data:write";
Process.Start(new ProcessStartInfo(requesturl) { UseShellExecute = true });
listener = new HttpListener();
listener.Prefixes.Add(url);
listener.Start();
Console.WriteLine("Listening for connections on {0}", url);
// Handle requests
Task<string> listenTask = HandleIncomingConnections();
this.code = listenTask.Result;
GetToken();
// Close the listener
listener.Close();
return code;
}
In order to access private user data you need the permission of the user to access it. The way you request permission is with the oauth2 consent screen this is standard part of Oauth2.
So no you cant automate that. AutoDesk-forgue does return a refresh token as part of its oauth2 flow.
What you can do is request authorization once store your refresh token and use the refresh token to request a new access token whenever you need to access the api again.
In this way your automation will run just fine without you.
Related
I have an elevated development account in Twitter.
I'm testing Tweetinvi with this code:
private async Task ConnectToTwitter()
{
// we create a client with your user's credentials
var userClient = new TwitterClient(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret);
toolStripStatusLabel1.Text = "Connected";
// request the user's information from Twitter API
var user = await userClient.Users.GetAuthenticatedUserAsync();
labelUserName.Text = user.Name;
// publish a tweet
var tweet = await userClient.Tweets.PublishTweetAsync("Hello tweetinvi world!");
Console.WriteLine("You published the tweet : " + tweet);
}
And I get this error:
Reason : Unauthorized
Code : 401
Date : 29/05/2022 15:25:49 +02:00
URL : https://api.twitter.com/1.1/statuses/update.json?status=Hello%20tweetinvi%20world%21&tweet_mode=extended
Twitter documentation description : Unauthorized - Authentication credentials were missing or incorrect.
On this line of code:
var tweet = await userClient.Tweets.PublishTweetAsync("Hello tweetinvi world!");
How can I add the credentials to the PublishTweetAsync call?
Or maybe, there is another way to publish a tweet with credentials without using PublishTweetAsync?
UPDATE
Due to the answer of Andy Piper, I have to say that the code compiles, so all the arguments for TwitterClient has a value (of course, I'm not going to share them here), and I can get the user here:
var user = await userClient.Users.GetAuthenticatedUserAsync();
I have also enabled this:
But I don't know what to put in the Callback URI.
The answer is in your codeā¦
// we create a client with your user's credentials
var userClient = new TwitterClient(ConsumerKey, ConsumerSecret, AccessToken, AccessTokenSecret);
You need to have the values defined in your code to pass in to the TwitterClient instance. You also need to ensure that you have an app with access to the v1.1 API (elevated access) to use this code, since it will not work with v2.
Finally, you should check that your app has read and write permissions and that your access token and secret were generated with these permissions.
I am implementing authentication using MSAL and I need some guidance for handling refresh tokens.
My Angular Web App is authenticating with my ASP.NET Web API using MSAL. Web API requires some scopes for accessing Microsoft Graph, so it uses "On Behalf Of" OAuth 2.0 flow to get an access token for calling MS Graph. This part is done and works.
The problem is that MS Graph will be called after some time by my .NET daemon app (using OBO flow) when access token will expire.
What I need is to get refresh token by my Web API and cache it (e.g. in SQL database) so it can be read by daemon app and used to obtain a valid access token.
I suppose that the TokenCache for the confidential client application is the right way to do this but I'm not sure how to get a valid access token by daemon app.
Here is the code of my daemon app I want to use to get access token from AAD:
var userAssertion = new UserAssertion(
<accessToken>,
"urn:ietf:params:oauth:grant-type:jwt-bearer");
var authority = authEndpoint.TrimEnd('/') + "/" + <tenant> + "/";
var clientCredencial = new ClientCredential(<clientSecret>);
var authClient = new ConfidentialClientApplication(<clientId>, authority, <redirectUri>,
clientCredencial, <userTokenCache>, null);
try
{
var authResult =
await authClient.AcquireTokenOnBehalfOfAsync(<scopes>, userAssertion, authority);
activeAccessToken = authResult.AccessToken;
}
catch (MsalException ex)
{
throw;
}
Should I provide <userTokenCache> to get the refresh token form cache? If yes, UserAssertion requires an <accessToken> to be provided, but I don't know what value should be used.
Or should I make a token request on my own and get the refresh token from the response since it is not supported by MSAL? Then I could store the refresh token in the database and use it as <accessToken> with null as <userTokenCache> in daemon app.
I thought it is possible to get the refresh token using MSAL, but I found it is not.
Update
I forgot to say that all of my apps use the same Application ID (this is due to the limitations of the AADv2 endpoint, although I just found that it was removed from the docs at Nov 2nd 2018).
Why not client credentials flow?
Communication with MS Graph could be performed in Web API (using OBO flow) but the task may be delayed by the user, e.g. send mail after 8 hours (Web API will store tasks in the database). The solution for this case is an app (daemon) that runs on schedule, gets tasks from the database and performs calls to MS Graph. I prefer not to give admin consent to any of my apps because it is very important to get consent from the user. If the consent is revoked, call to MS Graph should not be performed. That is why the daemon app should use the refresh token to get access token from AAD for accessing MS Graph (using OBO flow).
I hope it is clear now. Perhaps I should not do it this way. Any suggestion would be appreciated.
MSAL does handle the refresh token itself, you just need to handle the cache serialization. - the userTokenCache is used by the OBO call, and you use the refresh token by calling AcquireTokenSilentAsycn first (that's what refreshes tokens)
- the applicationTokenCache is used by the client credentials flow (AcquireTokenForApplication).
I'd advise you to have a look at the following sample which illustrates OBO: https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2, in particular TodoListService/Extensions/TokenAcquisition.cs#L275-L294
the code is :
var accounts = await application.GetAccountsAsync();
try
{
AuthenticationResult result = null;
var allAccounts = await application.GetAccountsAsync();
IAccount account = await application.GetAccountAsync(accountIdentifier);
result = await application.AcquireTokenSilentAsync(scopes.Except(scopesRequestedByMsalNet), account);
return result.AccessToken;
}
catch (MsalUiRequiredException ex)
{
...
Now the cache is itself initialized from the bearer token that is sent by your client to your Web API. See
TodoListService/Extensions/TokenAcquisition.cs#L305-L336
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");
}
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)
{
...
The scenario: I have 2 web-apps. One of them is [an authorization server][1] (implementing by IdentityServer4), the other is [a client][1]. They do interact by [Authorization Code grant][2].
The end-user work with the client app using Angular2 on front-end. To let her to login (through the auth server app as third side like Facebook etc) and get JWT-token (the issuer is the client app) I created the following middleware handling requests which is sended by end-user after succesfull authorization on authorization server side (i.e. the incoming request must contain auth code):
using IdentityModel.Client;
public async Task Invoke(HttpContext httpContext)
{
if (!httpContext.Request.Path.Equals("/api/connect/authcallback", StringComparison.Ordinal))
{
await next(httpContext);
return;
}
//try to get auth code from the request
string code = httpContext.Request.Form["code"];
//try to request access token from the auth server app
var tokenClient = new TokenClient("https://AuthServer.com/connect/token", ClientId, ClientSecret);
var responseToken = await tokenClient.RequestAuthorizationCodeAsync(code, "http://ourcallback.com");
var token = responseToken.AccessToken;
//that's good, so create JWT-token for the end-user
var JwtToken = JsonConvert.SerializeObject(CreateJwtToken());
//what should I do further?
}
My question is how can I pass the JWT-token to the end-user's Angular2 app? It's wrong to just send it from that point of code because Angular2 have to set it to LocalStorage. Maybe should I redirect user with the token? So can I do it (how to pass it)?
[1]: https://www.rfc-editor.org/rfc/rfc6749#page-6
[2]: https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1
To authenticate with AzureAD I put the folling Code in an Console Application
private static async Task<string> GetAuthTokenAsync(string tendent,string AppIdUri , string ClientID)
{
/*
<add key="ida:Audience" value="https://mehler.ws/ToDoWebApi" />
<add key="ida:ClientID" value="f0e91727-3edd-4b00-9630-591166a74e4b" />
*/
var authContext = new AuthenticationContext(string.Format("https://login.windows.net/{0}", tendent));
AuthenticationResult result = authContext.AcquireToken(AppIdUri, ClientID , new Uri(Settings.Default.WebApiReplyAdress));
return result.CreateAuthorizationHeader();
}
the Method AcquireToken Shows a Screen where I am asked to Input my Credentials.
I accidently selected the Account I log in with in Windows 10. Now the Screen doesn't show up any more an the application uses my Windows 10 Account automatically. Does anyone know how to fix this Problem, so that the Screen shows up again?
Token's are cached to alleviate complexity in your app. You will need to clear the token cache if you want the user to log back in... typically you would setup a logout function.
More information on token cache: http://www.cloudidentity.com/blog/2013/10/01/getting-acquainted-with-adals-token-cache/
How to logout:
authContext.TokenCache.Clear();
string requestUrl = "https://login.microsoftonline.com/{0}/oauth2/logout?post_logout_redirect_uri={1}";
Task.Run(async () =>
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
var response = await client.SendAsync(request);
});
{0} - Fully qualified name of your Azure Active Directory e.g.
yourad.onmicrosoft.com or tenant id.
{1} - The URL of your application where a user must be redirected
back after the logout is complete. This should be properly URL
encoded.
An easy way is to pass to AcquireToken PromptBehavior.Always, there's an overload for that. That will cause ADAL to ignore the cache and will ask the service for a clean prompt
I found a very simple Solution myself to once clear the Cache.
Delete Cookies in Internet Explorer / Edge ;-)
Thanks anyway for the Answers hot to implement proper Logout Code and Force Prompt for Login allways.
https://components.xamarin.com/gettingstarted/xamarin.auth
So that website shows how to authenticate the user, and how to make requests, but it skips the step in between which is getting the access token out of the url. This is probably really simple but this is the first time I am working with API's. If someone could view that website and find out exactly how I am supposed A.) Find the url with the access token in it(I know the authentication link redirects you to it in a browser, but in Xamarin.Auth, after authenticating, you go straight back to the app instead of the redirect url. B.) to extract the access token out of the url. thanks.
Uncheck "Disable implicit OAuth" in your client's security settings on the Instagram site.
var auth = new OAuth2Authenticator (
clientId: "CLIENT_ID",
scope: "basic",
authorizeUrl: new Uri ("https://api.instagram.com/oauth/authorize/"),
redirectUrl: new Uri ("REDIRECT_URL"));
auth.AllowCancel = allowCancel;
// If authorization succeeds or is canceled, .Completed will be fired.
auth.Completed += (s, ee) => {
var token = ee.Account.Properties ["access_token"];
};
var intent = auth.GetUI (this);
StartActivity (intent);
For other services you can just use OAuth2Request to execute your protected requests.