Use Dropbox access token without going through the authorization flow - c#

I've got a Generated access token from DropBox ".....fquCiA_pW5SsJal2C.......".
I'm using the following code to upload a file-
static void Main()
{
// Uncomment the following line or manually provide a valid token so that you
// don't have to go through the authorization process each time.
//var accessToken = GetAccessToken();
// var accessToken = new OAuthToken("token", "secret");
var api = new DropboxApi(ConsumerKey, ConsumerSecret, accessToken);
var file = api.UploadFile("dropbox", #"myFolder\b.jpg", #"b.jpg");
Console.WriteLine(string.Format("{0} uploaded.", file.Path));
}
There is an instruction in the code that I can use a token. So, I have used-
var accessToken = "...lkasjdfsdlfjsadlj...";
But it shows invalid argument error. Where shall I use that key?
Please help?
I've taken the code from here

Related

Get AccessToken for Azure Storage from InteractiveBrowserCredential

I'm trying to get an accesstoken from a InteractiveBrowserCredential so I can make calls to the Azure Datalake, but when I try to do this I get this error message:
System.Net.Http.HttpRequestException: 'Response status code does not
indicate success: 403 (Server failed to authenticate the request. Make
sure the value of Authorization header is formed correctly including
the signature.).'
Below is my code, I sspect it might be the scopes I request but I have tried every value I could find online (https://storage.azure.com/user_impersonation, https://storage.azure.com/.default).
// setup authentication
var tenantId = "common";
var clientId = "xxx";
var options = new InteractiveBrowserCredentialOptions {
TenantId = tenantId,
ClientId = clientId,
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
RedirectUri = new Uri("http://localhost"),
};
// authenticate and request accesstoken
var interactiveCredential = new InteractiveBrowserCredential(options);
var token = interactiveCredential.GetToken(new TokenRequestContext(new[] { "https://storage.azure.com/.default" }));
// Create HttpClient
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); ;
string res = await client.GetStringAsync("https://xx.blob.core.windows.net/?comp=list"); // this line throws the error
textBox1.Text = res;
If I use the SDK it does work, so it does not appear to be security settings.
// connect to Azure Data Lake (this works fine)
string accountName = "xxx";
string dfsUri = "https://" + accountName + ".dfs.core.windows.net";
var dataLakeServiceClient = new DataLakeServiceClient(new Uri(dfsUri), interactiveCredential);
// get filesystems
var systems = dataLakeServiceClient.GetFileSystems().ToList();// works fine
The error "403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signatureerror" usually occurs if you have not x-ms-version header in your code.
I agree with Gaurav Mantri, To resolve the error make sure to pass header value.
I tried to reproduce the same in my environment and got the same error as below in Postman:
I generated the access token by using the below Parameters:
https://login.microsoftonline.com/common/oauth2/v2.0/token
grant_type:authorization_code
client_id:4b08ee93-f4c8-47e9-bb1e-XXXXXXX
client_secret:client_secret
scope:https://storage.azure.com/user_impersonation
redirect_uri:https://jwt.ms
code: code
When I included x-ms-version=2019-02-02, I am able to access the storage account successfully like below:
The x-ms-version header value must be in the format YYYY-MM-DD.
In your code, you can include the header below samples:
Client.DefaultRequestHeaders.Add("x-ms-version", "2019-02-02");
request.Headers.Add("x-ms-version", "2019-02-02");
Reference:
Versioning for the Azure Storage services | Microsoft Learn

Is it possible use AuthorizeAttribute with a external api call?

i'm working with asp mvc 5, and i have to schedule some tasks, so i want to create a simple methods to be called from a simple console program C# and schedule them with Windows Task Scheduler.
The think is, i'm using Identity with Authorize attribute to manage the user permissions.
For example, i have the next method:
[Authorize(Roles="Admin")]
public async Task<JsonResult> CriticalTask(string someParam)
{
//procesing data
return null;
}
The think, is:
I dont know how can i do the login to pass the validation from the Authorize(Roles="Admin")
I try creating a simple method to login before it, but that doesn't work
I'm trying some like this
const string URL = "http://localhost:53665/";
RestClient mClient = new RestClient(URL);
const string parameterUserName = "userName";
const string parameterPassword = "password";
const string ruta = "Usuarios/ApiLogin";
var request = new RestRequest(ruta);
request.AddParameter(parameterUserName, "userName");
request.AddParameter(parameterPassword, "password");
//Method to login
var result2 = mClient.Execute(request);
Console.WriteLine($"Login\n{result2.Content}");
//Method that needs Admin permissions
request = new RestRequest("Usuarios/Test");
var result3 = mClient.Execute(request);
Console.WriteLine($"Test\n{result3.Content}");
is that possible only with Authorize attribute? or i need to implement some token method to authorize this calls?
Thanks!
What you should do is to save the received token after login and then add the token to request header which needs to be authorized:
var result = mClient.Execute(request);
string resultContent = result.Content.ReadAsStringAsync().Result;
//This token will be used for authorization
var token = JsonConvert.DeserializeObject<TokenModel>(resultContent);
var request = new RestRequest("Usuarios/Test"); //add token to header of request
mClient.AddDefaultHeader("Authorization", string.Format("bearer {0}", token.Access_Token));
var result3 = mClient.Execute(request);
Token model:
public class TokenModel
{
...
public string Access_Token { get; set; }
...
}
The easiest solution would be to use BasicAuth - you pass Credentials in headers for each request, and each request is validated separately - search for MVC Basic auth fr sample setup. I's the easiest form - but also very insecure as you pass your credentials in each call in almost plain text (it is only base64 of your credentials)
I'd suggest you to use Identity Server 4 to authorize your client using bearer token.
this way before first call you request token from server and then pass it to following requests and use this to authorize your api calls.
see following tutorial about setup.
http://docs.identityserver.io/en/aspnetcore1/quickstarts/6_aspnet_identity.html
in following url you can see example of in memory users, but also token requests.it's easy but obsolete
https://neelbhatt.com/2018/03/04/step-by-step-setup-for-the-auth-server-and-the-client-identityserver4-with-net-core-part-ii/
you can also use some sort of following code to obtain token in less obsolete way:
using (var httpClient = new HttpClient()) {
var discovery = await _httpClient.GetDiscoveryDocumentAsync(_configuration["ApiBaseAddress"]);
if (discovery.IsError)
{
return false;
}
request.Address = discovery.TokenEndpoint;
request.ClientId = _configuration["AuthClientName"];
request.ClientSecret = _configuration["AuthClientSecret"];
var request = new PasswordTokenRequest
{
UserName = "yourUserName",
Password = "yourPassword"
};
var token = await _httpClient.RequestPasswordTokenAsync(request);
}
in token.AccessToken you have your access token - the one needed to be sent to call api. you also have your refresh token in token.RefreshToken - it will be useful later
then to send call simply add bearer token to your HttpRequestMessage and it's done
var _httpClient = new HttpClient();
//Configure your http client here
var req= new HttpRequestMessage("http request method", "request uri");
req.SetBearerToken("your access token goes here);
var result = await _httpClient.SendAsync(req);
keep in mind that after you receive permission denied it's better to refresh token than obtain another one (you don't need to send your credentials). You use your refresh token i mentioned earlier.
The code for refreshing token is very similar to obtaining token by login/password. Just instead of PasswordTokenRequest class use following class:
var request = new RefreshTokenRequest
{
RefreshToken = _refreshToken
};
and instead httpClient.RequestPasswordTokenAsync(request) use httpClient.RequestRefreshTokenAsync(request). rest of code may remain similar.
I end up creating a custom attribute, based on the reply posted by crrlos in StackOverflow in Spanish.
I will translate it as best I can so that it can serve others
What you can do is create a custom authorization attribute, for that
you create a class that inherits AuthorizeAttribute and override the
AuthorizeCore method. The modification consists in passing to the
route an additional parameter to indicate that it is calling from the
task scheduler, if the parameter is not found then it will perform the
normal validation, if the parameter is found (it must have a value or
if it will not be null ) Then take the credentials of the url and
perform the validation, if they are correct return a true allowing
access to the method.
public class CustomAuthorization : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//get special parameter indicating that the request was made from the task scheduler
var parametro = httpContext.Request.QueryString.Get("parametro_especial");
if(parametro != null)
{
// get access credentials and validate them
// if they are valid, return true
}
//if they are not valid, or aren't present
//try with deffault validate.
return base.AuthorizeCore(httpContext);
}
}
How to use it?
[CustomAuthorization (Roles = "Admin")]
public JsonResult CargarTodosLosArticulos()
{
return null;
}

Issues Accessing Microsoft Graph API Data

Currently having issues integrating Microsoft Graph API, into my ASP.NET Core 2.2 Web Application(MVC). That uses "Work or Schools Accounts" : “Cloud – Single Organisation” using Two Factor Azure Sign-on Authentication.
Using Code Sample 1 code I'm attempting to GET the graph query: -
https://graph.microsoft.com/v1.0/me/
returning the surname from the response header
The issue that i'm experiencing at the moment is that i'm receiving an error at the line of code: -
var objMessages = objGraphClient.Me.Request().GetAsync().Result;
With the error message : "does not exist or one of its queried reference-property objects are not present".
// #############
// Code Sample 1
// #############
// Graph Api.
string strResource = "https://graph.microsoft.com";
string SecretId = "<Secret Id>";
// Azure Ad.
Uri strInstance = new Uri("https://login.microsoftonline.com/");
string strDomain = "<Domain>.onmicrosoft.com";
string strTenantId = "<Tenant Id>";
string strClientId = "<Client Id>";
string strCallbackPath = "/signin-oidc";
// The authority to ask for a token: your azure active directory.
string strAuthority = new Uri(strInstance, strTenantId).AbsoluteUri;
AuthenticationContext objAuthenticationContext = new AuthenticationContext(strAuthority);
ClientCredential objClientCredential = new ClientCredential(strClientId, SecretId);
// Acquire Token.
AuthenticationResult objAuthenticationResult = objAuthenticationContext.AcquireTokenAsync(strResource, objClientCredential).Result;
// Get bearer token.
GraphServiceClient objGraphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async request =>
{
// This is adding a bearer token to the httpclient used in the requests.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", objAuthenticationResult.AccessToken);
}));
// The next line produces an error :: does not exist or one of its queried reference-property objects are not present.
var objResult = objGraphClient.Me.Request().GetAsync().Result;
Debug.WriteLine($"{objResult.Surname}");
If I change Code Sample 1 above to Code Sample 2 below passing in the tokenPlease() requested that’s obtained from Microsoft Graph Explorer after successful login, this works, returning the surname successfully, indicating that their is an issue possible in my Bearer token: -
// #############
// Code Sample 2
// #############
// Get bearer token.
GraphServiceClient objGraphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
async request =>
{
// This is adding a bearer token to the httpclient used in the requests.
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer","ERf54f2f...Etc");
}));
// The next line now works.
var objResult = objGraphClient.Me.Request().GetAsync().Result;
Debug.WriteLine($"{objResult.Surname}");
Any help on this would be much appreciated!
You are using the ADAL library which uses the old Azure AD V1 authentication endpoint. You should be using the MSAL Library which uses the Azure AD V2 authentication endpoint.
I would suggest making your life easy and go grab the Microsoft.Graph.Auth Nuget package and then use this code instead of having to create your own
DelegateAuthenticationProvider
IConfidentialClientApplication clientApplication = AuthorizationCodeProvider.CreateClientApplication(clientId, redirectUri, clientCredential);
AuthorizationCodeProvider authenticationProvider = new AuthorizationCodeProvider(clientApplication, scopes);

Swagger UI will return API data, but my Authorized calls return "permission denied"

So I believe my APIservice should be fine since I can return results through Swagger? I am calling from a WPF project. I launch the program and it asks me to login, then it continues and will tell me I don't have permission.
I'm super green to WebAPI2 and think I may just be constructing my call incorrectly. It does seem that I get a token back correctly from my site, the only issue is when I try to actually call on the API for data.
Here is my code:
public static string clientId = "{#Calling App Id}";
public static string commonAuthority = "https://login.windows.net/{#my Azure AD tenant}";
public static Uri returnUri = new Uri("http://MyDirectorySearcherApp");
const string ResourceUri = "https://{#Api App Service}.azurewebsites.net";
public static async Task<List<User>> LoadBands(IPlatformParameters parent)
{
AuthenticationResult authResult = null;
List<User> results = new List<User>();
try {
//get token or use refresh
AuthenticationContext authContext = new AuthenticationContext(commonAuthority);
if (authContext.TokenCache.ReadItems().Count() > 0)
authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
authResult = await authContext.AcquireTokenAsync(ResourceUri, clientId, returnUri, parent);
} catch (Exception ee) {
throw ex;
}
using (var httpClient = new HttpClient()) {
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, $"{ResourceUri}/api/Band/")) {
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
using (var response = await httpClient.SendAsync(request)) {
string responseData = await response.Content.ReadAsStringAsync();
//responseData always equals "You do not have permission to view this directory or page"
return results;
}
}
}
Edit: Maybe helpful to note I'm using a DataAPI that is called by a Rest API, the rest API is secured by Azure AD.
Edit: I'm calling from a Portable Class Library.
Edit: Well, I'm getting authenticated but it does not appear to make any difference. If I completely remove the Auth header I get the same result
It seems that the token is incorrect for the web API which protected by Azure AD. Please check the aud claim in the token which should match the Audience you config in the web API project. You can check the aud claim by parse the token from this site.
And if you still have the problem please share the code how you protect the web API.
Update
If you were using the Express mode like below, you need to acquire the access_token using the app which you associate with the web API.
If you were using the Advanced mode, we should also use the that app to acquire the token and the ResourceUri should matched the value you config in ALLOWED TOKEN AUDIENCES like below:

InstaSharp: Can not get the access token

I am using InstaSharp in a WPF application. I have read the documentation of InstaSharp. And here is the code I tried.
InstagramConfig config = new InstagramConfig(clientId, clientSecret, redirectUri, realtimeUri);
var oAuth = new OAuth(config);
var scopes = new List<OAuth.Scope>();
var link = InstaSharp.OAuth.AuthLink(config.OAuthUri + "authorize", config.ClientId, config.RedirectUri, scopes, InstaSharp.OAuth.ResponseType.Code);
var authInfo = await oAuth.RequestToken(clientId);
Now the problem is that I am getting authInfo as null. Which means I am getting the accesstoken as null. When I copy paste the link(generated by above code) in the browser, it asks me for authorization and generates an access token but I can not get it programmatically with the above code.
Can someone please help me get the access token ?

Categories