restforce / restforce

A Ruby client for the Salesforce REST API.
MIT License
812 stars 358 forks source link

Restforce::UnauthorizedError: INVALID_SESSION_ID: Session expired or invalid #284

Open cmalpeli opened 7 years ago

cmalpeli commented 7 years ago

Hello,

I'm using the omniauth-saleforce gem to perform OAuth authentication between my app and my customers Salesforce instance. They can successfully authenticate and grant my app the token and refreshtoken, however after a period of time the session expires with the following message:

Restforce::UnauthorizedError: INVALID_SESSION_ID: Session expired or invalid

What am I doing wrong? Should I be requesting a new token via the existing connection?

Thanks!

cmalpeli commented 7 years ago

I am actually still having this issue. I thought it was because I didn't have the authentication_callback: Proc.new { |x| Rails.logger.debug x.to_s } statement, but I included that and the session still expires after some time....

timrogers commented 7 years ago

@cmalpeli Will try to look into this over the next few days.

cmalpeli commented 7 years ago

Thanks @timrogers here is the relevant code from my class initializer:

def initialize(options = {})

    if Rails.env.production?
      sales_force_client_id       = ENV['SALESFORCE_CLIENT_ID']
      sales_force_client_secret   = ENV['SALESFORCE_CLIENT_SECRET']
    else
      sales_force_client_id       = ENV['SALESFORCE_SANDBOX_CLIENT_ID']
      sales_force_client_secret   = ENV['SALESFORCE_SANDBOX_CLIENT_ID_SECRET']
    end
    @client = Restforce.new oauth_token: options[:salesforce_token],
      refresh_token: options[:salesforce_refresh_token],
      instance_url:  options[:salesforce_instance_url],
      client_id:     sales_force_client_id,
      client_secret: sales_force_client_secret,
      authentication_callback: Proc.new { |x| Rails.logger.debug x.to_s }
  end
cmalpeli commented 7 years ago

@timrogers any ideas here? Am I simply doing something wrong?

timrogers commented 7 years ago

I've been having a think about this, but I'm not sure what's going wrong to be honest.

Could you try enabling logging (see https://github.com/ejholmes/restforce#loggingdebugginginstrumenting) and see what it outputs? I'm wondering how it's messing up the authentication process and whether there's something odd going on with refresh tokens or something (since the gem seems to work for me and everyone else!).

timrogers commented 7 years ago

Looks pretty odd to me. Could it not just be that your access token isn't valid? You might want to ask Salesforce when they give that API response. On Sat, 4 Feb 2017 at 18:53, Christian Malpeli notifications@github.com wrote:

Sure - here you go

CREATE CONTACT D, [2017-02-04T12:49:51.560270 #55889] DEBUG -- request: url: "https://cs13.salesforce.com/services/data/v38.0/sobjects/Contact" method: :post headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXX-REPLACED-XXXXXXX"} body: "{\"LastName\":\"Employer\",\"FirstName\":\"I am a \",\"MailingCountry\":\"United States\",\"MailingPostalCode\":\"29464\",\"MailingCity\":\"Mount Pleasant\",\"MailingState\":\"South Carolina\",\"Phone\":\"1-212-767-9223\",\"Business_Contactc\":true,\"RecordTypeId\":\"01238000000UVfW\"}" D, [2017-02-04T12:49:52.011590 #55889] DEBUG -- response: status: "401" headers: {"date"=>"Sat, 04 Feb 2017 17:49:48 GMT", "x-content-type-options"=>"nosniff", "x-xss-protection"=>"1; mode=block", "content-security-policy"=>"reflected-xss block;report-uri /_/ContentDomainCSPNoAuth?type=xss, referrer origin-when-cross-origin", "set-cookie"=>"BrowserId=sXP1DwCxRgqFKfZjHEDo3A;Path=/;Domain=.salesforce.com;Expires=Wed, 05-Apr-2017 17:49:48 GMT", "expires"=>"Thu, 01 Jan 1970 00:00:00 GMT", "www-authenticate"=>"Token", "content-type"=>"application/json;charset=UTF-8", "transfer-encoding"=>"chunked", "connection"=>"close"} body: "[{\"message\":\"Session expired or invalid\",\"errorCode\":\"INVALID_SESSION_ID\"}]" D, [2017-02-04T12:49:52.012487 #55889] DEBUG -- request: url: "https://cs13.salesforce.com/services/data/v38.0/sobjects/Contact" method: :post headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXX-REPLACED-XXXXXXX"} body: "{\"LastName\":\"Employer\",\"FirstName\":\"I am a \",\"MailingCountry\":\"United States\",\"MailingPostalCode\":\"29464\",\"MailingCity\":\"Mount Pleasant\",\"MailingState\":\"South Carolina\",\"Phone\":\"1-212-767-9223\",\"Business_Contactc\":true,\"RecordTypeId\":\"01238000000UVfW\"}" D, [2017-02-04T12:49:52.302464 #55889] DEBUG -- response: status: "401" headers: {"date"=>"Sat, 04 Feb 2017 17:49:48 GMT", "x-content-type-options"=>"nosniff", "x-xss-protection"=>"1; mode=block", "content-security-policy"=>"reflected-xss block;report-uri /_/ContentDomainCSPNoAuth?type=xss, referrer origin-when-cross-origin", "set-cookie"=>"BrowserId=iaExNnU2QV2dxeGyE2yQpA;Path=/;Domain=.salesforce.com;Expires=Wed, 05-Apr-2017 17:49:48 GMT", "expires"=>"Thu, 01 Jan 1970 00:00:00 GMT", "www-authenticate"=>"Token", "content-type"=>"application/json;charset=UTF-8", "transfer-encoding"=>"chunked", "connection"=>"close"} body: "[{\"message\":\"Session expired or invalid\",\"errorCode\":\"INVALID_SESSION_ID\"}]" D, [2017-02-04T12:49:52.303152 #55889] DEBUG -- request: url: "https://cs13.salesforce.com/services/data/v38.0/sobjects/Contact" method: :post headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXX-REPLACED-XXXXXXX"} body: "{\"LastName\":\"Employer\",\"FirstName\":\"I am a \",\"MailingCountry\":\"United States\",\"MailingPostalCode\":\"29464\",\"MailingCity\":\"Mount Pleasant\",\"MailingState\":\"South Carolina\",\"Phone\":\"1-212-767-9223\",\"Business_Contactc\":true,\"RecordTypeId\":\"01238000000UVfW\"}" D, [2017-02-04T12:49:52.620522 #55889] DEBUG -- response: status: "401" headers: {"date"=>"Sat, 04 Feb 2017 17:49:49 GMT", "x-content-type-options"=>"nosniff", "x-xss-protection"=>"1; mode=block", "content-security-policy"=>"reflected-xss block;report-uri /_/ContentDomainCSPNoAuth?type=xss, referrer origin-when-cross-origin", "set-cookie"=>"BrowserId=bVDVYiDVRPieZJrqnLZuJw;Path=/;Domain=.salesforce.com;Expires=Wed, 05-Apr-2017 17:49:49 GMT", "expires"=>"Thu, 01 Jan 1970 00:00:00 GMT", "www-authenticate"=>"Token", "content-type"=>"application/json;charset=UTF-8", "transfer-encoding"=>"chunked", "connection"=>"close"} body: "[{\"message\":\"Session expired or invalid\",\"errorCode\":\"INVALID_SESSION_ID\"}]" D, [2017-02-04T12:49:52.621282 #55889] DEBUG -- request: url: "https://cs13.salesforce.com/services/data/v38.0/sobjects/Contact" method: :post headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXX-REPLACED-XXXXXXX"} body: "{\"LastName\":\"Employer\",\"FirstName\":\"I am a \",\"MailingCountry\":\"United States\",\"MailingPostalCode\":\"29464\",\"MailingCity\":\"Mount Pleasant\",\"MailingState\":\"South Carolina\",\"Phone\":\"1-212-767-9223\",\"Business_Contactc\":true,\"RecordTypeId\":\"01238000000UVfW\"}" D, [2017-02-04T12:49:52.916055 #55889] DEBUG -- response: status: "401" headers: {"date"=>"Sat, 04 Feb 2017 17:49:49 GMT", "x-content-type-options"=>"nosniff", "x-xss-protection"=>"1; mode=block", "content-security-policy"=>"reflected-xss block;report-uri /_/ContentDomainCSPNoAuth?type=xss, referrer origin-when-cross-origin", "set-cookie"=>"BrowserId=JOTCVfX-QUOQZB7hfuKFSA;Path=/;Domain=.salesforce.com;Expires=Wed, 05-Apr-2017 17:49:49 GMT", "expires"=>"Thu, 01 Jan 1970 00:00:00 GMT", "www-authenticate"=>"Token", "content-type"=>"application/json;charset=UTF-8", "transfer-encoding"=>"chunked", "connection"=>"close"} body: "[{\"message\":\"Session expired or invalid\",\"errorCode\":\"INVALID_SESSION_ID\"}]" rake aborted! Restforce::UnauthorizedError: INVALID_SESSION_ID: Session expired or invalid /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/middleware/raise_error.rb:11:in on_complete' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/response.rb:9:inblock in call' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/response.rb:57:in on_complete' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/response.rb:8:incall' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday_middleware-0.11.0.1/lib/faraday_middleware/response/follow_redirects.rb:78:in perform_with_redirection' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday_middleware-0.11.0.1/lib/faraday_middleware/response/follow_redirects.rb:66:incall' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/middleware/instance_url.rb:9:in call' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/middleware/authorization.rb:9:incall' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday_middleware-0.11.0.1/lib/faraday_middleware/request/encode_json.rb:24:in call' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/middleware/multipart.rb:14:incall' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/middleware/mashify.rb:6:in call' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:inbuild_response' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in run_request' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/faraday-0.9.2/lib/faraday/connection.rb:177:inpost' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/concerns/verbs.rb:35:in block in define_verb' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/concerns/verbs.rb:61:inblock in define_api_verb' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/restforce-2.5.0/lib/restforce/concerns/api.rb:284:in create!' /Users/christianmalpeli/Dropbox/rails_projects/job_board/lib/salesforce.rb:38:increate_contact' /Users/christianmalpeli/Dropbox/rails_projects/job_board/lib/tasks/sftest.rake:28:in block in <top (required)>' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/gems/rake-12.0.0/exe/rake:27:in<top (required)>' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/bin/ruby_executable_hooks:15:in eval' /Users/christianmalpeli/.rvm/gems/ruby-2.3.3@jobboardio4.2.7/bin/ruby_executable_hooks:15:in

'

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/ejholmes/restforce/issues/284#issuecomment-277462813, or mute the thread https://github.com/notifications/unsubscribe-auth/AAHFpnXcbZqmiHnBkJ85ri12fTmNHZE9ks5rZLsXgaJpZM4LwLAy .

cmalpeli commented 7 years ago

Do you mean my oauth_token or my refresh_token? It works if I re-establish the connection and continues to work until I eventually get the expired message.

Do you have a sample vanilla snippet of connecting and performing an action I could use and swap out for my tokens?

cmalpeli commented 7 years ago

Hi @timrogers any further thoughts on this? I've submitted on their dev forums but not getting anything useful: https://developer.salesforce.com/forums/ForumsMain?id=9060G000000I4YQQA0

Cheers!

sicktastic commented 7 years ago

@cmalpeli What is your refresh token policy with your connected app?

cmalpeli commented 7 years ago

Hi @antwonlee it is currently set to:

Refresh Token Policy: Refresh token is valid until revoked

Makes no sense....

I can confirm as well that after what I understand to be the max token length time in SF (8hrs I think?) i'm getting a new Bearer token:

Yesterday: headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXXXXX779Om!AQoAQBUVsPh684uj2RBZDn5EKOkQhVRMx1VVOMrmohLVBe_ZPHrHszZjcD.1ZxNVW7wZ66MJsGh8PbCu2npOi9F5hZL9Sc3."}

This morning: headers: {"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/json", "Authorization"=>"OAuth XXXXXXXXXXAQoAQBUVsPh684uj2RBZDn5EKOkQhVRMx1VVOMrmohLVBe_ZPHrHszZjcD.1ZxNVW7wZ66MJsGh8PbCu2npOi9F5hZL9Sc3."}

sicktastic commented 7 years ago

Is "web" included in your Oauth scope?

I might run a test app just with restforce to see if it's your Salesforce configuration or its the combination of using omniauth-salesforce together.

What is your instance URL? I never used omniauth-salesforce before, but restforce middleware using refresh_token works fine on my app.

cmalpeli commented 7 years ago

Thanks @antwonlee

Sorry, where would I see if "web" is included in my scope?

Would you mind sharing how you are establishing your refresh_token in your app? If you are not using omniauth-salesforce how are you handle the OAuth?

sicktastic commented 7 years ago

@cmalpeli You can find the scope in your Salesforce connected app settings.

Setup > Apps > App Manager > Your App > Selected OAuth Scopes

Here is a simple Restforce Demo Rails App: https://goo.gl/R6YqGQ

class Salesforce
  include Singleton

  def restforce
    client ||= Restforce.new :oauth_token => ENV["SALESFORCE_OAUTH_TOKEN"],
        :refresh_token           => ENV["SALESFORCE_REFRESH_TOKEN"],
        :instance_url            => ENV["SALESFORCE_INSTANCE_URL"],
        :client_id               => ENV["SALESFORCE_CLIENT_ID"],
        :client_secret           => ENV["SALESFORCE_CLIENT_SECRET"],
        :authentication_callback => Proc.new {|x| Rails.logger.debug x.to_s}
  end
end

It's straight from the README file.

It's a simple CRUD app: https://restforce-demo.herokuapp.com/

You don't need omniauth-salesforce to handle OAuth with restforce. I believe that gem is like any other omniauth gems that enables your app to login with different providers.

You can read about refresh_token here: https://goo.gl/wfzV4n

@cmalpeli I am just troubleshooting with you, I am not totally sure if that is the actual problem.

Would you mind sharing how you are establishing your refresh_token in your app? If you are not using omniauth-salesforce how are you handle the OAuth?

@cmalpeli I didn't use gems like omniauth but manually requested through curl and set the token and other credentials in environment variables for the app. Perhaps, what you are trying to do with your app is more like this with omniauth-salesforce doing that process for user on its behalf?

cmalpeli commented 7 years ago

@antwonlee thanks for all your help - much appreciated.

I do have the web scope included (I've actually included all scopes just in case one of those being missing was the issue).

You are correct in your assumption, in the app, each user can authenticate to their SF instance via the 'omniauth-salesforce' gem.

Here is my test salesforce class:

https://gist.github.com/cmalpeli/238ef16f243e6c31a78c8ffbe10cfe43

So - the class is called using something like this:

    salesforce_token: t.salesforce_token, 
    salesforce_refresh_token: t.salesforce_refresh_token, 
    salesforce_instance_url: t.salesforce_instance_url)

And it all works for a while, but then eventually the session expires :(

sicktastic commented 7 years ago

@cmalpeli Sorry to hear that. It sounds frustrating. Are you storing the refersh_token in the database itself (like in the User's model)? I remember reading some people having database connection problem causing similar issues.

I think I will try creating a demo app using omniauth-salesforce and try to mimic what you are trying to do.

The 401 error is indicating that refresh_token was expired. So somewhere after initial Oauth dance, it might be still using the old refresh_token to authenticate rather than trying to catch the 401 error and try to re-authenticate.

That would be my guess.

cmalpeli commented 7 years ago

@antwonlee yes - I am storing the refresh_token in the db. It seems that restforce is failing to properly request/generate a new access_token once the initial access_token expires?

sicktastic commented 7 years ago

@cmalpeli I think you are right. I would start investigating here: https://github.com/ejholmes/restforce/issues/81 I have a feeling it is not restforce that is having issues, but somewhere between your database and the middleware not regenerating the token?

Let me know what you find. I will do some research too, and hopefully try to create a demo app that does what you are trying to do when I have some time.

cmalpeli commented 7 years ago

@antwonlee not sure if that is the issue - I am pulling out the refresh_token out of the DB without issue.

If I do something like:

puts u.salesforce_refresh_token
puts u.salesforce_token
puts u.salesforce_instance_url

  client ||= Restforce.new :oauth_token => u.salesforce_token,
        :refresh_token           => u.salesforce_refresh_token,
        :instance_url            => u.salesforce_instance_url,
        :client_id               => ENV['SALESFORCE_SANDBOX_CLIENT_ID'],
        :client_secret           => ENV['SALESFORCE_SANDBOX_CLIENT_ID_SECRET'],
        :authentication_callback => Proc.new {|x| Rails.logger.debug x.to_s}

I get the output of the tokens and then the Session error:

XXXREPLACEDXXXOjWzSFTnMxSFeBvT5n6tBOvKkjN3pNe6TTzX.iYEEC.0sRTKEN8s1dQKlDsYwJO.Zuj5JBwX7A74HX
XXXREPLACEDXXXOm!AQoAQOXWKBTLg6.A.mAxwQGbx_xy1FMQUGpXEZCEEHl.YarrmrXzA0fTgiHBks7nIcrMLxeZQjHAfQ_jbLYgKNH3DOOziqlA
https://cs13.salesforce.com
rake aborted!
Restforce::UnauthorizedError: INVALID_SESSION_ID: Session expired or invalid
cmalpeli commented 7 years ago

@antwonlee any suggestion on how to confirm/debug if restforce is requesting a new refresh_token?

sicktastic commented 7 years ago

Hey @cmalpeli Sorry my week was very full. Are you using any authentication gem or your own? I am going to try to create a demo app myself but will be doing with devise, omniauth-salesforce, restforce.

cmalpeli commented 7 years ago

hi @antwonlee I'm using Devise. Thx!

cmalpeli commented 7 years ago

@antwonlee just a small update - even if I hardcode the auth values, I still get the [{\"message\":\"Session expired or invalid\",\"errorCode\":\"INVALID_SESSION_ID\"}] once my token expires.

@client ||= Restforce.new(oauth_token: "XXXXXXXr5_NBUS3gPhmEo_WpsxXdFK0FhwsMqZhiKJ5UvLm2vid6Y15cArBl2tYz61oPOYHsefBSjlCUel9Jae3.Wj",
                     refresh_token: "XXXXXXzSFTnMxSFeBvT5n6tBOvKkjN3pNe6TTzX.iYEGnwBuovvlXyrBLspr3VM_NbFxDA6KgB17Zd8.x", 
                     instance_url: "https://XXX.salesforce.com",
                     client_id: sales_force_client_id,
                     client_secret: sales_force_client_secret,
                     authentication_callback: Proc.new { |x| Rails.logger.debug x.to_s },
                     api_version: '38.0')

Additional update, if I do a POST to https://test.salesforce.com/services/oauth2/token outside of Restforce

I get a proper access_token


{
  "access_token": "xxxxxxx779Om!AQoAQHqfFMcHQEO662dYZS7fCZRZnCG7CCEg2ytpY_PjLwWyIxwHDhaJvbtEQ3LtoDKTE9tnhzxNEEhpNhPHsMB1LpGNFphB",
  "signature": "xxxx5rFy5UZEgtWT+qcq4Int8Br5GJckahfKmo=",
  "scope": "refresh_token visualforce wave_api custom_permissions web openid chatter_api id api eclair_api full",
  "instance_url": "https://xxx.salesforce.com",
  "id": "https://test.salesforce.com/id/xxxxxxx0779OmMAI/x004gsNsxxxxxxxxAAI",
  "token_type": "Bearer",
  "issued_at": "1487792089090"
}```
sicktastic commented 7 years ago

Hey @cmalpeli! I had some time this weekend to play around with this with devise omni-salesforce and restforce. Are you initializing this in your controller or your config/initializer folder?

I don't think you can call in the current_user.refresh_token that you stored in the database into initialization process—which I think is causing to not go through the middleware process.

Does that make sense? That is my current status as well. If I initiate through my controllers with User's stored tokens from the first OAuth process, it expires and gives me the invalid_token error like you are getting. (Hitting the 5 Use count limit)

sicktastic commented 7 years ago

Here is a sample app I am working on for this process: https://restforce-omniauth-salesforce.herokuapp.com/

cmalpeli commented 7 years ago

@antwonlee this is awesome - I'll try to mirror this - makes sense! I was traveling so sorry for the delayed response.

On Sat, Mar 11, 2017 at 1:01 AM, Anthony Lee notifications@github.com wrote:

Hey @cmalpeli https://github.com/cmalpeli I am not sure if you are still trying to fix this, but I was able to fix the token problem with this: https://github.com/restforce/restforce-omniauth-salesforce- demo-app/blob/master/app/models/user.rb#L18-L27 in the User model and using this: https://github.com/restforce/restforce-omniauth-salesforce- demo-app/blob/master/app/controllers/accounts_controller.rb#L4-L6 in your controller.

Hope that helps.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ejholmes/restforce/issues/284#issuecomment-285845976, or mute the thread https://github.com/notifications/unsubscribe-auth/AA2_VlJbjF7VbA6pNqLeiQhyLAeiWkLWks5rkjipgaJpZM4LwLAy .

sicktastic commented 7 years ago

@cmalpeli I am still trying to figure out your issue. When I manually put tokens in initializers it works fine, but when I try to initiate restforce through controllers or services or models—I am getting the same issue you are having.

Hopefully we can fix this!

sicktastic commented 7 years ago

@cmalpeli the demo app https://restforce-omniauth-salesforce.herokuapp.com/ seems to be working fine now. It's been few days and it still didn't have a token problem with my Salesforce production—not the developer edition.

timrogers commented 7 years ago

@antwonlee Do you have a handle on what change you've made has fixed it? It'd be great to document this for others.

sicktastic commented 7 years ago

@timrogers I think more documentation the better. First of all, I think it will be nice to document what people need to configure on the Salesforce side. As for Rails, things started to work when I did a before_action https://github.com/restforce/restforce-omniauth-salesforce-demo-app/blob/master/app/controllers/accounts_controller.rb#L3 with current_user values from the database. I am not totally sure why yet, but it is working and the tokens seem to refresh itself as it should.

Whenever I have some time, I can document more here too: https://github.com/restforce/restforce-omniauth-salesforce-demo-app

kevinjbayer commented 7 years ago

I appear to be having this same issue. I was attempting to use Restforce without the omniauth gem, but I need the connection to remain persistent after a user logs in to SalesForce from my app. Until I saw this issue, I thought it was the way I was handling the callback (see below), which I'm still not sure is the best way to handle it or if the id_token is even the correct refresh_token, but it's all I saw in the response. I don't need to authenticate my users via omniauth, just need to be able send data automatically via that persistent connection. Any updates to this issue since March?

class SalesforceController < ApplicationController

  def callback
    @admin = current_user
    newparams = { grant_type: 'authorization_code', client_id: ENV['SALESFORCE_CLIENT_ID'], client_secret: ENV['SALESFORCE_CLIENT_SECRET'], redirect_uri: 'http://localhost:3000/salesforce/callback', code: params[:code] }
    x = Net::HTTP.post_form(URI.parse('https://login.salesforce.com/services/oauth2/token'), newparams)
    response = eval(x.body)
    @admin.sf_token = response[:access_token]
    @admin.sf_refresh_token = response[:id_token]
    @admin.sf_instance_url = response[:instance_url]
    @admin.save!
    redirect_to dashboard_settings_path
  end

end

Editing to add my controller, which is also in a before_action and still causing this issue.

class ApplicationController < ActionController::Base

  before_action :salesforce, :if => :current_user

  private

  def salesforce
    if current_user.sf_token.present?
      @restforce ||= Restforce.new(oauth_token: current_user.sf_token,
                                   instance_url: current_user.sf_instance_url,
                                   api_version: '39.0',
                                   client_id: ENV['SALESFORCE_CLIENT_ID'],
                                   client_secret: ENV['SALESFORCE_CLIENT_SECRET'],
                                   authentication_callback: Proc.new {|x| Rails.logger.debug x.to_s})
    else
    end
  end

end
kevinjbayer commented 7 years ago

Turns out I needed to enable the OAuth Scope (Perform requests on your behalf at any time (refresh_token, offline_access)) in order to get the refresh_token in the response. Will update tomorrow morning if that clears the expiration issue for me, as I suspect it may.

Edit - Nope, session is still expiring.

kevinjbayer commented 7 years ago

I'm a bozo. I forgot to add the refresh_token when I was initializing the Restforce instance. It appears to be working properly now.

dclausen commented 7 years ago

For anyone else that's getting bitten by this, I was getting the same INVALID_SESSION_ID error but only in the sandbox environment. I had incorrectly used "test.salesforce.com" as the host instead of the same domain name as the instance_url.

jcabasc commented 6 years ago

Hey @kevinjbayer - thanks for sharing your scenario. I'm wondering, how do you get the refresh_token in the first place. Which action/request did you use?. It's been a long time I know.

kevinjbayer commented 6 years ago

@jcabasc I believe most of it can be gleaned from the code I put above. I'm manually making the call in my controller, and @admin.sf_refresh_token should grab response[:refresh_token], not [:id_token]. It has been a minute so I can't recall exactly, but let me know if there's something more specific you need help with.

heironimus commented 5 years ago

I had this exact problem, but only on sandbox orgs. It was because I was not setting the host to "test.salesforce.com" for sandbox orgs as mentioned here

drewish commented 4 years ago

I was also bit by not setting the host. I opened up https://github.com/restforce/restforce/pull/507 to try to updated the docs so they clarify the need to set the host option.

anandsrivastav commented 4 years ago

I am using the sandbox developer account and getting the same issue.

In my case I am not getting refresh toke in response.

Please let me know the solutions.

akarath commented 3 years ago

I'm able to authenticate using username and password flow. But it fails when I try to use the other two. Can someone please guide me with the step by step approach for the same?

hasmanyguitars commented 6 months ago

My issue was that I was forgetting to set the client_id or client_secret during the 2nd request.

Restforce.configure do |config|
    config.client_id     = x
    config.client_secret = y
end

This was causing oauth_refresh? to return false here: https://github.com/restforce/restforce/blob/main/lib/restforce/concerns/authentication.rb#L40

cgs commented 2 months ago

Had this in sandbox. Needed to set host option to "test.salesforce.com" NOT "https://test.salesforce.com"