I am using salesforce rest api to access the salesforce account from my rails app.I created a remote access app and got the key N the id. I was able to authenticate the user and get the auth_token, instance url and all that. But, when I send request at "instance_url/services/data/v20.0" along with the access token , I get this error:
[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]
I have a developer salesforce account and have API enabled true for every profile, except for the "Authenticated website" profile(which is not accessible).
Please, can anybody help me with this?
I'm authenticating the user with following request
HTTParty.post "login.salesforce.com/services/oauth2/token";, :body=>{"grant_type"=>"authorization_code","code"=>"abc}","client_secret"=>"abc", "client_id"=>"abc","format"=>"json","redirect_uri"=>"localhost:3000/salesforce/callback";}
which is returning signature, id, instance_url, issued_at, access_token and refresh_token
HTTParty.get "ap1.salesforce.com/services/data/v20.0";, :headers=>{"Authentication"=>"OAuth access_token", "Content-Type"=>"application/json"}
which responds with
[{"errorCode"=>"INVALID_SESSION_ID", "message"=>"Session expired or invalid"}]
How are you passing the sessionId to the /services/data/v20.0 request?, if your access_token is abc123 then you need a http header of Authorization: OAuth abc123 in the request.
API session in salesforce expires regardless if there are activities or not.
to set the duration of each session go to Setup > Administration Setup > Security Controls > Session Settings>
the max is 8hours.
cheers!
Additionally to the other possible problems identified by the other answers, the Lock sessions to the IP address from which they originated setting in Salesforce is a possible contributing factor to otherwise valid code. From the following Salesforce KB article:
Description
When "Lock sessions to the IP address from which they originated" is enabled, if an OAuth2 access token is used to perform a Salesforce REST API call, INVALID_SESSION_ID might be returned even if the token is obtained in the same Apex transaction.
Resolution
"Lock sessions to the IP address from which they originated" is strict, and internal IP addresses are not automatically whitelisted in this case. Since the login callout and subsequent REST API callouts might be performed via different internal IP addresses, INVALID_SESSION_ID might be returned when using the access token if the mentioned preference is enabled.
To solve this you may use the continuous IP enforcement feature (introduced in Summer '15):
Turn "Lock sessions to the IP address from which they originated" OFF,
Turn "Enforce login IP ranges on every request" ON,
Select the connected app's IP relaxation policy "Enforce IP restriction", and
Add Salesforce's internal IP range 10.0.0.0 to 10.255.255.255 to the list of profiles needing to use Salesforce's REST API.
or simply relax the IP restrictions:
Turn "Lock sessions to the IP address from which they originated" OFF, and
Select the connected app's IP relaxation policy "Relax IP restrictions"
If you are using Oauth you need to use Refresh Token flow, on this error to get a new renewed token. Here are more details : http://wiki.developerforce.com/index.php/Digging_Deeper_into_OAuth_2.0_on_Force.com
Please search for "refresh token" in the WIKI page link above.
Issues I ran into:
Make sure to include the scope "web" in the authorize request, e.g.
https://login.salesforce.com/services/oauth2/authorize?response_type=code&clientId=xxx&redirect_uri=http://www.example.com&scope=id+api+refresh_token+web
Use the instanceUrl that is returned in the authorize response. In my case this was https://eu2.salesforce.com and I always tried to use https://na1.salesforce.com which didn't work
Faced the same issue and in my case < > characters in the password were causing the problem.
I am adding this answer because any of other answers above helped me. My problem was actually that I was using access_token as I received it in the JSON response during login.salesforce.com/services/oauth2/token requests.
You have to remove ID from access_token, as it is described in SalesForce documentation: "Substitute the ID for the token value"
Related
I am a newbie in integrating APIs and so I am encountering some issues that need help.I have been working with Clash of Clans API for some weeks. I want to make a website where users can make request and get data from the server. **To use the API, a JSON Web Token is required and it needs to be passed as part of every request. The token is bound to rate limitations and specified IP addresses. **
What I have been doing is, create a token with my IP address, get the token and make request using it. Now, I want to take this a step forward but I have no idea how to take request from users around the world.
I thought of taking keyword from the user and making request from the server but don't know the step forward. Or maybe I should make requests using my server's address from my PC? Which I don't know how. I will appreciate it if someone could explain to me with this in layman's language and if possible through a reference. Thank you in advance.
There are many ways to design for Clash of Clans API architecture.
I just to make a simple design base on quick review of Clash of Clans limitation.
API_KEY can add IP address only when create API_KEY.
It means can't update (add) user IP address after create API_KEY.
Step 0 : Create API_KEY
Clash of Clans server only allow specified IPs and API_KEY for REST API call.
You need to know your server IP v4 address(production purpose) and your IP address(debugging purpose)
your IP address get from google search
After create key, you (developer), develop(or debugging) your API.
This is created API KEY in CC server
This example, using Postman check API.
Step 1 : User login
With his User ID and password. it will save into your server with hashed value.
(It means not save password, save hashed data). it can verify but if leak to hacker much more safe.
Use request API call(or service) to your server
Step 2 : Your server forward API to CC server
Server verify user is valid
If valid user, server forward API call into Clash of Clans(CC) server by CC API with API_KEY(Bearer Token)
Step 3 : CC server check correct API call
CC server verify by compare called API_KEY/IP address with saved API_KEY/IP address
Step 4 : CC server return API response to your server
Your server received the server API call
Step 5 : Your server return to user
User received her request a service
This API list
You can test it from your home.
This is example API call via CC server's documentation
I am following this guide (https://learn.microsoft.com/en-us/skype-sdk/ucwa/authenticationusingazuread) in order to access Skype for Business. Everything goes fine till the last part but let's do step by step. I am building my .net console application to do this but in order to explain you properly the problem I am having I will show you directly the http calls through Insomnia (software used to make http calls).
Step 1:
GET request towards https://webdir.online.lync.com/autodiscover/autodiscoverservice.svc/root
I hit 200 and as answer I receive this:
Step 2:
I use the user link.
So I send an http request to https://webdir1e.online.lync.com/Autodiscover/AutodiscoverService.svc/root/oauth/user and I get a 401 Unauthorized (everything still correct).
In the header of the answer it points me to the Identity Provider to ask for authorization (authorization_uri)
Step 3: I use that link to authorize my app, which has its own client_Id (that I hide in the following screenshot).
This is how I compose the call:
If I send this http request I get redirected to the page where it asks my personal login and by inserting my credentials I succesfully login and hit 404, where in the answer I receive back my access token.
Step 5: I use the access token towards the same AutodiscoverService link of step 1. This is to register my application. I hit 200 and I receive back the link to access Skype for Business.
Finally (and this is where things go wrong) I send a POST request towards the applications link with the Bearer token, and I receive a 403 Forbidden. I think I am following correctly the guide but I can't figure out why I can access the resource at the last step.
EDIT:
The permissions are granted. I hide the name since it contains the name of my company. But it is the same of the domain of my login.
So the token you generated authorizes you to access resources at https://webdir1e.online.lync.com which you've done to fetch a new set of resources including the "application" resouce which is on a DIFFERENT host: https://webpooldb41e14.infra.lync.com.
You actually have to get another OAuth token now which authorizes you for the application resource and then you can POST to that to generate your session in UCWA.
As a side note... If you've defined your own single-tenant application in Azure that has been granted rights to SkypeForBusinessOnline then I think you should be targeting authorization and authentication endpoints of the form:
https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/authorize
https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/token
Also I should add, if you're trying to write a trusted secure client that users in your company will use I would suggest looking up the Resource Owner Password Credentials auth flow. It allows you to directly hit the token endpoint I mentioned above and exchange username/password credentials for an access token. Then you can manage auto-discovery and application creation easily under the hood without getting re-directed back and forth to Azure.
https://learn.microsoft.com/mt-mt/azure/active-directory/develop/v2-oauth-ropc
Posted this on github and was told to come here ask for help
Hello!
I am trying to implement custom authentication for my resources on Google Cloud Storage using this module with a service account. I am trying to abstract away the need for a Google account for my end users.
What the ideal workflow would look like:
User queries https://cdn.example.com/[[BUCKET]]/[[FILENAME]] using Bearer token
The API on that end intercepts the bucket and file name and checks the validity of the token
The API then would request the resource at https://storage.cloud.google.com/[[BUCKET]]/[[FILENAME]]
Step 3 Returns the Location header that I will pass over to the user
After snooping around a bit I found out that the Location header returned in step 3 in the form of https://[[DATA]].googleusercontent.com/download/storage/v1/b/[[BUCKET]]/o/[[FILENAME]]?qk=[[KEY]] is a public link that can be accessed by anonymous users too. Which is exactly what I want. However while using the storage API I can only see selfLink and mediaLink, not the link above.
I tried using google-auto-auth to sign the request with my service account towards the storage.cloud.google.com endpoint but I get an Unauthorized error.
From looking here I understand that to access the storage.cloud.google.com is based on cookie authentication, which google-auto-auth doesn't seem to do. All it does is add a Bearer token to the header of the request.
This looks like you need signedUrls
Yea, that would be great, if it didn't expose the email of the service account.
Cheers!
TL;DR How to get the redirect URL from storage.cloud.google.com links using a service account?
Say the page where user can update his own profile: profile_update.php?id=1234567...(user's Google id).
Question:
How can I restrict access with the returned authResult or me? (I mean which item in the object will help that, not how to get these item out).
or Do I still need to build a server side $_SESSION for that?
You could do some validation on the client side using the auth result, but you'd also want to verify that the request you get on the server side is from who you think it is from to prevent cross-site request forgery attacks. So you'd need something that validate that the POST that update the profile came from an authenticated user, not just that the POST data was in the correct format. So typically, your form will send a specific code (a CSRF token) and that same token must be present in the user's cookies (or a server side session token, which in PHP can be accessed via $_SESSION).
I've been reading lots of documentation about Google API access and OAuth flow using it but I don't seem to get it working in my mind, so I want to get some help first in order to have a clear idea about how it works then I can code it using the corresponding API.
What I want to achieve is feed a Java application running in a PC with specific Google user data, like localization through Google Latitude API. In order to get this, OAuth must be used, so I need getting the user consent, then access the user data from the application running in my computer, and I don't know how to manage this.
I've already registered my application with the Google APIs Console and enabled the Google Latitude module. I've also tried the Latitude console application here and it works properly (a browser tab opened asking for a Google user; I entered it and I got the location data), but I'm having problems when trying to adapt the program flow to my needs.
In my application, the 'remote' user is supposed to send a request (a custom JSON message) to the server asking for service enable/disable, like allowing the server to track his/her position through Latitude. Then, AFAIK, the server should send to the user a URL so the user can give the consent, but I don't know how to get this URL and how the server realizes about this consent and gets the token (automatically? Google tracks this authorization process?). Once my server gets the specific user token, then I should be ready to get service data for that user using the received token.
As I said before, I've tried according to different references, but as the documentation seems to be really scattered and much of it is already deprecated, I've been unable to get it working.
Judging from your description, the installed app OAuth2 flow seems to be the right one for you.
At some point, presumably when a user is installing your desktop app, you should fire up a browser - either embedded one in your app or the default browser - and sent them to this Google OAuth2 endpoint. In your request, fill out all the parameters as required by the doc: Latitude API scope, client_id, etc. Google, as an authorization server, will take care of user authentication, session selection, and user consent. If the user grants access to her data to your API, you will receive an authorization code either in the title of the browser window or at a localhost port.
Once you have the code, you can exchange it for an access token and a refresh token. The access token is what you need to call the API and access the user's data. It is short lived though - check the expired_in parameter in the response, I believe it is 3600 sec. - so you will need to periodically ping the token endpoint with your long lived refresh token and exchange it for an access token.
You can find a more thoroough description of this flow in the doc linked above.