Get access_token using Windows Service's or Console App. for Instagram Api - oauth

My windows service is collect instagram datas from instagram api. I was using client_id but this uses format is removed.
Instagram api is want to access_token but Oauth 2.0 is web-based. or not?
I using .NET and my application type is windows service and web request don't work because this call url: "https://www.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code" is have one more contain redirect. so web response haven't contain my web application link also auto redirect is open..
what should I do?
Thanks..

Steps to get instagram access token
register ur application in instagram account.
get a client id and client secret.
Step 1: HIT the below url.
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
step 2: after hitting above url you will be taken to login page. enter the login credentials and take the code from address bar.
it will be live for only 20 seconds i guess.
step 3: The code which you got put it in CODE parameter in the below source code, then run the below code in console application n hit breakpoint at response. you will get access token and userid.
public void GetDataInstagramToken()
{
try
{
NameValueCollection parameters = new NameValueCollection();
parameters.Add("client_id", "CLIENT-ID");
parameters.Add("client_secret", "CLIENT-Secret");
parameters.Add("grant_type", "authorization_code");
parameters.Add("redirect_uri", "REDIRECT-URI");
parameters.Add("code", "CODE");
WebClient client = new WebClient();
var result = client.UploadValues("https://api.instagram.com/oauth/access_token", "POST", parameters);
var response = System.Text.Encoding.Default.GetString(result);
// deserializing nested JSON string to object
var jsResult = (JObject)JsonConvert.DeserializeObject(response);
string accessToken = (string)jsResult["access_token"];
}
catch (Exception)
{
//exception catch
}
}

Related

Call Graph API from MVC App

SUMMARY UPDATE:
I got a sample working today thanks to the many good replies. Thanks all. My primary goal was to get current user information (ME) without using secret key. First I just used the secret key from the App Reg and this will authenticate the App and not the user. This does of course not work when calling ME. My next finding was if you want the users token, you still need the App Reg token, and then you request the users token. This requires less permissions on the App Reg, but requires to request two tokens. I ended up skipping ME and just requesting information for a specified user (through the APp Reg permissions):
$"https://graph.microsoft.com/v1.0/users/{email}/$select=companyName"
Both both approaches should be viable. I updated code below with working sample.
I am trying to do a very simple call to graph API to get companyName from current user. Found some samples but they seemed to be very complicated. The MVC app is authenticated trough an Application Registration in AAD.
I guess the application registration needs to be authorized to access Graph API. Or is more needed here? Getting company name should be fairly simple:
https://graph.microsoft.com/v1.0/me?$select=companyName
Does anyone have a snippet for calling the graph API, my best bet would be you need to extract a bearer token from the controller? ALl help is appreciated.
Working snippet:
public async Task<ActionResult> Index()
{
string clientId = "xxx";
string clientSecret = "xxx";
var email = User.Identity.Name;
AuthenticationContext authContext = new AuthenticationContext("https://login.windows.net/xxx.onmicrosoft.com/oauth2/token");
ClientCredential creds = new ClientCredential(clientId, clientSecret);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", creds);
HttpClient http = new HttpClient();
string url = $"https://graph.microsoft.com/v1.0/users/{email}/$select=companyName";
//url = "https://graph.windows.net/xxx.onmicrosoft.com/users?api-version=1.6";
// Append the access token for the Graph API to the Authorization header of the request by using the Bearer scheme.
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
HttpResponseMessage response = await http.SendAsync(request);
var json = response.Content.ReadAsStringAsync();
return View();
}
To add one last item, here is a link to an MVC sample on Git that uses an MVC application to send email. It illustrates how to call the MS Graph API to get various pieces of information. Keep in mind, if you are using an application only scenario, ME will not work, the sample illustrates how to obtain a delegated token for a user and use that toke to do work:
https://github.com/microsoftgraph/aspnet-connect-rest-sample
If I am reading this code snippet correctly, You are requesting a application only token for the Graph.Microsoft.Com resource, then attempting to use that toke with this URI:
url = "https://graph.windows.net/thomaseg.onmicrosoft.com/users?api-version=1.6"
This will not work because you are mixing resources, AAD Graph and MS Graph. The ME endpoint does not make since in this scenario because you are using the application only flow. This flow does not support the ME endpoint. ME is designed for use with a delegated token. the ME endpoint represents the signed in user, since and application is not a user, ME is meaningless.
You will need to target the user specifically:
https://graph.microsoft.com/v1.0/Users/[UPN or ID of user]?$select=companyName
Should work if your application has been granted the appropriate permission scopes.

Microsoft Graph API access token validation failure

I use this URL to get id_token:
https://login.microsoftonline.com/common/oauth2/authorize?
response_type=id_token%20code&
client_id=MY_CLIENT_GUID_ID_IN_HERE&
redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fopenid%2Freturn&nonce=alfaYYCTxBK8oypM&
state=6DnAi0%2FICAWaH14e
and this return result like this
http://localhost:3000/auth/openid/return?
code=AAA_code_in_here&
id_token=eyJ0eXAi_xxxx_yyyy_in_here&
state=6DnAi0%2FICAWaH14e&
session_state=xxxx_guid_xxxxx
and then i use the id_token to query Graph (use POST man)
i have see this post InvalidAuthenticationToken and CompactToken issues - Microsoft Graph using PHP Curl but make no sense.
OATH 2.0 requires multiple steps. The first request returns an OAUTH Code. The next step is converting that OATUH code into a Bearer Token. This is the step you are missing here.
I would also recommend using the v2 Endpoint which is a lot easier to work with (particularly with Graph). I wrote a v2 Endpoint Primer that walks through the process and may be helpful as well.
You can't use the token directly, there is one more step to exchange the code you get from the response url into token.
Here is my C# code (using Microsoft.IdentityModel.Clients.ActiveDirectory)
public static AuthenticationResult ExchangeCodeForToken(string InTenantName, string InUserObjId, string InRedirectUri, string InApplicationAzureClientID, string InApplicationAzureClientAppKey)
{
Check.Require(!string.IsNullOrEmpty(InTenantName), "InTenantName must be provided");
Check.Require(!string.IsNullOrEmpty(InUserObjId), "InUserObjId must be provided");
if (CanCompleteSignIn) //redirect from sign-in
{
var clientCredential = new ClientCredential(InApplicationAzureClientID, InApplicationAzureClientAppKey);
var authContext = new AuthenticationContext(Globals.GetLoginAuthority(InTenantName), (TokenCache)new ADALTokenCache(InUserObjId)); //Login Authority is https://login.microsoftonline.com/TenantName
return authContext.AcquireTokenByAuthorizationCode(VerificationCode, new Uri(InRedirectUri), clientCredential, Globals.AZURE_GRAPH_API_RESOURCE_ID); //RESOURCE_ID is "https://graph.microsoft.com/"
}
return null;
}
I had this issue today when I was playing with graph API, the problem in my case was how I was generating the token.
I used postman for generating the token wherein the Auth URL section I was adding the resource = client_id whereas it should be the graph URL. After making that change I was able to make the call via postman.
In order for the above to work, please make sure your application in Azure has delegated permissions to access the Graph API.
To receive the access token and use it for profile requests, you don't need anything from server-side, you can implement the oAuth2 just from the client side.
Use the following URL for login:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=YOUR_CLIENT_ID&resource=https://graph.microsoft.com&response_type=token&redirect_uri=YOUR_REDIRECT_URI&scope=User.ReadBasic.All
After successful login, user will redirected to the page with access_token parameter. Then use the following AJAX call to fetch user info:
var token = login_window.location.href.split('access_token=').pop().split('&')[0];
$.ajax({
url: "https://graph.microsoft.com/v1.0/me",
type: "GET",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', 'Bearer '+token);},
success: function(data) {
alert('Hi '+data.displayName);
console.log(data);
}
});
Note that you may need to enable oauth2AllowImplicitFlow:true setting from your Azure Active Directory application manifest file.
Set "oauth2AllowImplicitFlow": false to "oauth2AllowImplicitFlow": true.
Lastly, ensure that your app has required permissions for Microsoft Graph which are sign in users and View users' basic profile
An updated answer to get access with new applications:
Register your app in the app registration portal.
Authorization request example:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=offline_access%20user.read%20mail.read&state=12345
Authorization response will look like this:
https://localhost/myapp/?code=M0ab92efe-b6fd-df08-87dc-2c6500a7f84d&state=12345
Get a token
POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Host: https://login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&scope=user.read%20mail.read
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq3n8b2JRLk4OxVXr...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps
Use the access token to call Microsoft Graph
GET https://graph.microsoft.com/v1.0/me
Authorization: Bearer eyJ0eXAiO ... 0X2tnSQLEANnSPHY0gKcgw
Host: graph.microsoft.com
Source:
https://learn.microsoft.com/en-us/graph/auth-v2-user?context=graph/api/1.0
You can also get an access token without a user, see here:
https://learn.microsoft.com/en-us/graph/auth-v2-service

MVC 5 Identity 2 and Web API 2 authorization and call api using bearer token

The following scenario: I have an MVC 5 web app using Identity 2.0 and Web API 2.
Once the user authenticates in MVC 5 he should be able to call a WEB API endpoint let's call it: api/getmydetails using a bearer token.
What I need to know is how can I issue the token for that specific user in MVC 5?
I did solve this.
Here are some screenshots and I will also post the demo solution.
Just a simple mvc 5 with web api support application.
The main thing you have to register and after login. For this demo purpose I registered as admin#domain.com with password Password123*.
If you are not logged in you will not get the token. But once you loggin you will see the token:
After you get the token start Fiddler.
Make a get request to the api/service endpoint. You will get 401 Unauthorized
Here is the description of the request:
Now go to the web app, stage 1 and copy the generated token and add the following Authorization header: Authorization: Bearer token_here please notice the Bearer keyword should be before the token as in the image bellow. Make a new request now:
Now you will get a 200 Ok response. The response is actually the user id and user name that show's you are authorized as that specific user:
You can download the working solution from here:
http://www.filedropper.com/bearertoken
If for some reason the link doesn't work just let me know and I will send it to you.
P.S.
Of course in your app, you can use the generated bearer token to make ajax call to the web api endpoint and get the data, I didn't do that but should be quite easy ...
P.S. 2: To generate the token:
private string GetToken(ApplicationUser userIdentity)
{
if (userIdentity == null)
{
return "no token";
}
if (userIdentity != null)
{
ClaimsIdentity identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Name, userIdentity.UserName));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userIdentity.Id));
AuthenticationTicket ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
DateTime currentUtc = DateTime.UtcNow;
ticket.Properties.IssuedUtc = currentUtc;
ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
string AccessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
return AccessToken;
}
return "no token";
}

Instagram API returning error when requesting access_token on Windows Phone

I've been trying to integrate the Instagram API in my app, but am stuck with the authentication. I had it working completely fine when I was just using the implicit flow version which gave me the access_token as part of the URI fragment.
However, now I'm changing to the server-side flow, in which I receive a code after the user logs in. I then post this code to the access token URL, which will then give me the access_token as well as certain information about the user, such as their username and profile picture link.
I am using the InstaSharp library, modifying the source code.
HttpClient client = new HttpClient { BaseAddress = new Uri(config.OAuthUri + "access_token/", UriKind.Absolute) };
var request = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);
request.AddParameter("client_secret", config.ClientSecret);
request.AddParameter("client_id", config.ClientId);
request.AddParameter("grant_type", "authorization_code");
request.AddParameter("redirect_uri", config.RedirectUri);
request.AddParameter("code", code);
return client.ExecuteAsync<OAuthResponse>(request);
After creating my request, it is formatted as so:
{Method: POST, RequestUri: 'https://api.instagram.com/oauth/access_token/?client_secret={CLIENT_SECRET}&client_id={CLIENT_ID}&grant_type=authorization_code&redirect_uri=http://instagram.com &code={CODE}', Version: 1.1, Content: , Headers: { }}
(I inserted the space between the redirect_uri and code because it wouldn't let me post the question otherwise)
Everything appears normal in the address, but I always receive an error in the retuned json file:
"{"code": 400, "error_type": "OAuthException", "error_message": "You must provide a client_id"}"
I have no clue what is causing this error. Any help is greatly appreciated!
Thanks!
Elliott
Are you using the latest version of InstaSharp? Fork it here. You can check the README.md there although it's a bit outdated and you need to tweak some config. Here's how you can do it with the latest version that is in github:
// create the configuration in a place where it's more appropriate in your app
InstaSharpConfig = new InstagramConfig(
apiURI, oauthURI, clientId, clientSecret, redirectUri);
// then here's a sample method you can have to initiate auth
// and catch the redirect from Instagram
public ActionResult instagramauth(string code)
{
if (string.IsNullOrWhiteSpace(code))
{
var scopes = new List<InstaSharp.Auth.Scope>();
scopes.Add(InstaSharp.Auth.Scope.likes);
var link = InstaSharp.Auth.AuthLink(
oauthURI, clientId, redirectUri, scopes);
// where:
// oauthURI is https://api.instagram.com/oauth
// clientId is in your Instagram account
// redirectUri is the one you set in your Instagram account;
// for ex: http://yourdomain.com/instagramauth
return Redirect(link);
}
// add this code to the auth object
var auth = new InstaSharp.Auth(InstaSharpConfig);
// now we have to call back to instagram and include the code they gave us
// along with our client secret
var oauthResponse = auth.RequestToken(code);
// save oauthResponse in session or database, whatever suits your case
// oauthResponse contains the field Access_Token (self-explanatory),
// and "User" that'll give you the user's full name, id,
// profile pic and username
return RedirectToAction("action", "controller");
}
Take note that you can split up the "instagramauth" method. Did it that way for brevity.

can't get access token using refresh token

I wrote desktop application on java, which have access to the Google drive. (it just uploads and downloads files).
At the moment access type is online. when I need to access files/folders to the drive, I
redirect he browser to a Google URL and get access code:
String code = "code that was returned from brouser"
GoogleTokenResponse response = flow.newTokenRequest(code).setRedirectUri(REDIRECT_URI).execute();
GoogleCredential credential = new GoogleCredential().setFromTokenResponse(response);
everything works well! but I need to have that redirection only first time.
When I google, in the Google Drive API documentation I found that I can get refresh token via browser redirection and save it on DB for instance. (In the other word, I can use offline access).
And every time when I need to read data from google drive, I get access token using refresh token without redirection. is not it?
so I get refresh token like that:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=695230079990.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/drive&response_type=code&redirect_uri=https://localhost
question 1
I get code, from the browser redirecting. it's refresh token, is not it?
now, I need to get access token using that refresh token.
$.ajax({
type: "POST",
url: 'https://accounts.google.com/o/oauth2/token',
data: {
client_id: "695230079990.apps.googleusercontent.com",
client_secret: 'OWasYmp7YQ...4GJaPjP902R',
refresh_toke: '4/hBr......................xwJCgQI',
grant_type: 'refresh_token'
},
success: function(response) {
alert(response);
}
});
but I have error 400;
question 2) when I try to change redirect url I have that error: *
Invalid parameter value for redirect_uri: Non-public domains not allowed: https://sampl.ecom
so, must I create web applications Client ID , instead of installed application from google APIs console? Can't I change Redirect URI in installed application? I'm confused, I don't know, which should I use.
1) when you try to have offline access, you get authorization code which may be redeemed for an access token and a refresh token.
For isntance:
https://accounts.google.com/o/oauth2/auth?access_type=offline
&approval_prompt=auto
&client_id=[your id]
&redirect_uri=[url]
&response_type=code
&scope=[access scopes]
&state=/profile
after you get authorization code, you cat get refresh token.
static Credential exchangeCode(String authorizationCode)
throws CodeExchangeException {
try {
GoogleAuthorizationCodeFlow flow = getFlow();
GoogleTokenResponse response =
flow.newTokenRequest(authorizationCode).setRedirectUri(REDIRECT_URI).execute();
return flow.createAndStoreCredential(response, null);
} catch (IOException e) {
System.err.println("An error occurred: " + e);
throw new CodeExchangeException(null);
}
}
See the section on Implementing Server-side Authorization tokens for more information.
and after you get refresh token , you must save it. see that sample for mor information.
2) If you don't have installed application, you should create web applications to change redirecting URL.

Resources