How to authenticate request with session tokens manually?

Hello!
Does anyone know how to authenticate request with session tokens manually in Rails?

hmac = params["hmac"]
host = params["host"]
shop = params["shop"]
timestamp = params["timestamp"]
# id_token = params["id_token"]

if shopify_session = params["session"]
  query_params = {
    host: host,
    session: shopify_session,
    shop: shop,
    timestamp: timestamp,
  }
else
  query_params = {
    host: host,
    shop: shop,
    timestamp: timestamp,
  }
end

sorted_query_string = query_params.sort.map { |k, v| "#{k}=#{v}" }.join("&")
calculated_hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new("sha256"), ENV["SHOPIFY_CLIENT_SECRET"], sorted_query_string)
ActiveSupport::SecurityUtils.secure_compare(hmac, calculated_hmac) // returns false

This was working on a standalone(non-embedded) app but this doesn’t work in embedded app?

Hey Remy!

Session token is not an HMAC but a JWT. You would need to decode the JWT.

We use python (Django) to decode it but I took some help from AI and got this code for ROR.

def verify_session_token
  session_token = request.headers['Authorization']
  
  begin
    payload = JWT.decode(
      session_token,
      Rails.configuration.shopify_api_secret,
      true,
      {
        algorithms: ['HS256'],
        aud: Rails.configuration.shopify_api_key,
        leeway: 10
      }
    ).first
    
    shop = URI.parse(payload['dest']).host
  rescue JWT::DecodeError => e
    puts "Invalid Token"
  end
end

Let me know if this helps.

1 Like

Thank you @prakhar.

request.headers['Authorization'] returns NULL

I think my question was not clear.
I want to validate incoming request from Shopify Admin.
When I open the embedded app, I get these params.

Sorry about that.

request.headers['Authorization'] is how we are passing the session token.

Based on your query parameters. You would actually have to do.

session_token = params['id_token']
1 Like

It worked. Thank you, @prakhar :pray:

1 Like