Response must exactly match validationToken query parameter - ruby-on-rails

I am using Microsoft Graph and had successfully set up the ability to create subscriptions and receive push notifications. However, the process of creating a subscription is no longer working and I am stumped.
2018-01-25T23:32:41.694741+00:00 app[web.1]:
OData::ClientError (400 InvalidRequest:
"Subscription validation request failed.
Response must exactly match validationToken query parameter."
from "https://graph.microsoft.com/beta/subscriptions"):
Code to return validationToken in response. When I curl, my response is exactly as it should be.
def outlook_subscription
render plain: params[:validationToken]
head 200
end

Nothing has changed on our end. Since when did you start seeing this problem ? Did you deploy any new version of your (or the backed library) code ?
Please check the request/response in your logs and check if they both match (case sensitive).

This work for me!
def outlook_subscription
render json: params[:validationToken], content_type: "plain/text", status: 200
end

Related

Rails API 422 Unprocessable Entity: No verification key available, heroku

I created a Rails API with a JWT authentication system and deployed it to Heroku. When I request the endpoints locally, all seems to be working fine but when I make requests to the live endpoints (i.e the Heroku deployed app) I get a: 422 Unprocessable Entity server error and the response body looks like this:
{
"message": "No verification key available"
}
The class responsible for encoding and decoding the auth token is defined as follows:
class JsonWebToken
# secret to encode and decode token
HMAC_SECRET = Rails.application.secrets.secret_key_base
def self.encode(payload, exp = 24.hours.from_now)
# set expiry to 24 hours from the creation time.
payload[:exp] = exp.to_i
# sign token with application secret
JWT.encode(payload, HMAC_SECRET)
end
def self.decode(token)
# get payload, first index in decoded Array
body = JWT.decode(token, HMAC_SECRET)[0]
HashWithIndifferentAccess.new body
# rescue from all decode errors
rescue JWT::DecodeError => e
# raise custom error to be handled by custom handler
raise ExceptionHandler::InvalidToken, e.message
end
end
I have an endpoint /signup where I can make a POST request to register a new user and POST /todos which is accessible and available only to registered users. Making a registration request works perfectly fine, but when I try to make the POST request to the /todos endpoint it raises an error.
The association between user and suit is 1:m respectively.
Please if you have any idea on how I can fix this, I'll be very grateful, thanks : ).
I finally figured a way out by altering the Rails.application.secrets.secret_key_base to Rails.application.secret_key_base. For a more detailed review on this please check out this link. Hopefully, this will help someone facing a similar issue.
This was also my problem. After checking out my json_web_token.rb file, I figured out that I had written the following line:
HMAC_SECRET = Rails.application.secrets.secret_key_base
There is an extra secrets reference, which is causing the problem. It should be:
HMAC_SECRET = Rails.application.secret_key_base
But as far as I'm concerned, you managed to figure it out yourself!

HTTP status code when sending email failed

Note: I have read this but I still don't know how to go about building the sending email function correctly, so I ask this question. I need to know the HTTP status code to use when email sending succeed/failed, or if that's not the right thing to do, the right thing to do.
A POST request to my rails app will send an email.
If the email sending failed, what HTTP status code should I return to the person who send the POST request in my JSON response?
def inform
delivered = true
begin
UserMailer.new_comment(current_user, other_user, #note).deliver_now
rescue Net::SMTPAuthenticationError, Net::SMTPServerBusy, Net::SMTPSyntaxError, Net::SMTPFatalError, Net::SMTPUnknownError
delivered = false
end
if delivered
# I use :created here because email is created
render json: { delivered: true }.to_json, status: :created
else
# I use :service_unavailable here because email sending failed
render json: { delivered: false }.to_json, status: :service_unavailable
end
end
502
bad_gateway
Typically used for upstream server failure.
Here's some more info: https://airbrake.io/blog/http-errors/502-bad-gateway-error
a 502 Bad Gateway Error means that a server that is upstream to one that you (the client) are connecting to has run into trouble. In this scenario, this means that the server providing the 502 Bad Gateway Error is acting as a gateway
I would rather use code 424 https://www.rfc-editor.org/rfc/rfc4918#section-11.4
The 424 (Failed Dependency) status code means that the method could
not be performed on the resource because the requested action
depended on another action and that action failed. For example, if a
command in a PROPPATCH method fails, then, at minimum, the rest of
the commands will also fail with 424 (Failed Dependency).

RoR JSON.parse catching an error

Writing an app that reaches out to an api (ETSY) and brings back some JSON but sometimes I get a 403 error and if I get an error I want to show an error page but I'm not sure how to check for that error and do something else.
my_hash = JSON.parse(open("https://openapi.etsy.com/v2/listings/#{$productId}?api_key=XXXX&fields=title,url,price,description&includes=MainImage").read)
I've looked around for a while but haven't seen what I'm looking for.
You can use a begin rescue block to redirect the user whenever you hit a 403 error
def index
begin
my_hash = JSON.parse(open("https://openapi.etsy.com/v2/listings/#{$productId}api_key=XXXX&fields=title,url,price,description&includes=MainImage").read)
rescue
redirect_to error_path
end
This is sort of quick and dirty, but I beileve it can get the job done.
This article may also help. http://www.mattjohnston.co/blog/2013/10/18/responding-with-errors-in-rails/
I think you need to check your api response, if the response is 404 then render error page. May be something like this. To getting response from api, you need to use third party like (restclient or httpparty).
def index
response = RestClient get "https://openapi.etsy.com/v2/listings/#{$productId}api_key=XXXX&fields=title,url,price,description&includes=MainImage"
unless response.code == 404
result_hash = JSON.parse(response.body)
// do something
else
// redirect to error page here
end
end
For reference, pls read restclient documentation here.

Rails API: How do you standardize your JSON responses?

Right now, upon a successful call to my Rails API Backend, I might do one of the following...
render json: {user_id: #user.id, token: token}
or
render json: {status: :success}
And upon an unsuccessful result, I may do something like
render json: {status: :failure, error: "The email or password entered is not correct."}
My question is... what's the best way to standardize this.
If my iOS app goes searching for a json dictionary value of dict[#"error"] it's not always going to find it. Should every single render message I have regardless of success... have a 'status' key, or an 'error' key or both.
Or is it better for the front end to deal with this, and if dict[#"error"]/dict[#"status"] happen to not exist... then it knows the back end did not have an error occur otherwise it would have said so?
The way you are rendering the responses is fine. On your client side, it's should be all about handling properly HTTP status codes.
render status: :ok -> should return a HTTP status code 200, which means a successful request. Then your client (iphone app) does know that with a successfull request you get the user id and token.
render status: :bad_request -> should return a HTTP status code 400, which means unsuccessfull request, then your client would know that an error occured, and based on your standards he can look up the error field of the json response
I had the similar question in terms of how do we standardize the JSON response.
By default Rails generates this sort of JSON from a post model,
posts: [
{
id: 22198,
title: "Using GitHub Pages To Host Your Website",
date: "2013-08-16 09:30:20",
},
{
id: 22196,
title: "Running Tests in Ruby on Rails – Treehouse Quick Tip",
date: "2013-08-15 14:30:48",
}
]
But is there any standard to power the Rails API for an iPhone APP?
What are the standards or typical success/failure response format an iOS developer would expect to see?

how do you write json response destroy methods correctly in rails?

Here's the code for sending a json response associated with a working and non working status. Does anyone have recommendations for other resources? This isn't working. Thank you.
if #content.destroy
format.json { redirect_to #collection, status: :destroyed, notice 'Content was removed from collection.' }, :status => 200
else
format.json { render json #content.errors, status: :unprocessable_entity }, :status => 400
end
TL;DR: if you are using some JS framework, then look up how that framework wants success and failure response to look like, if you are rolling your own - then do whatever makes more sense for you.
Long version:
There are couple ways you can return response from rails to your web app. Rails by default returns status code 2xx for success and 4xx for failed requests. Some web frameworks such as Extjs, like to receive response with 200 code always and look at success key in the response to see if the request was successfult. If you are writing your own JS that utilizes XHR, then you can do whatever you want: its up to you how you architect your API. I find it useful to return json response from server with 200 code and set success key to true or false so in my callback JS i can write something like:
if(request.data.success){
successfulPost(response);
} else {
failed(response);
}
one of the reasons I prefer that approach is that, if there is an exception, then I can actually distinguish from record not being saved due to validation errors as opposed to bug in code that caused exception. But that is a personal preference and some may argue that error is error and it does not matter what caused it.

Resources