riboseinc / ribose-api

API for Ribose
0 stars 0 forks source link

Migrate Log in & log out from Wiki to Apiary #3

Closed ribose-jeffreylau closed 7 years ago

ribose-jeffreylau commented 7 years ago

1

ribose-jeffreylau commented 7 years ago

@skalee Hi, would you be able to help with this? This should be a good starting point for familiarizing with the conversion workflow.

A skeleton file (sections/user_session.apib) has already been created. It just needs to be filled :)

Relevant existing doc can be found here in the Authentication section.

Cheers!

skalee commented 7 years ago

Sure.

Got a question, @ribose-jeffreylau or @ronaldtse. Contrary to most of the other requests, like space_member or calendar, user log in payload should be send as application/x-www-form-urlencoded, not application/json, am I correct?

ronaldtse commented 7 years ago

@skalee I believe so, the login endpoint is a bit different. @ribose-jeffreylau could you confirm?

skalee commented 7 years ago

I'm generally done with rewriting the documentation to API blueprint format. However, I have attempted to test documented requests, and they're not working. I don't know why.

The ribose-ruby client does not make typical API requests. It mimics a real browser with Mechanize: fetches the login page via GET /login, fills-in the form, and submits it. I suppose no page's JavaScript is involved, but I'm not sure about that. Anyway, I can confirm it works for my user name and password.

Wiki mentions seven request parameters, they are copied from login form correctly. However, all my attempts to request POST /login have ended with a redirection to /error_403. I believe it doesn't mean successful login. Normally when user and password do not match, Ribose server renders a login form and returns it via HTTP 200 OK response.

Perhaps it is some CSRF token failure. However I've made a GET /login request and copied the token from that form, it didn't help. Neither token obtained via https://www.ribose.com/csrf_meta worked.

This all led me to suspicion that some headers are required, and that's not documented in wiki. I have stopped my experiments at this point because it already took me couple of hours, and maybe someone here knows the answer. Maybe I'll do another attempt with fresh mind.

I can make a pull request (or simply push things to master, I don't see any pull requests in this repo) with what I have now, that is wiki content translated to API Blueprint format. That said, I doubt if examples which do not work are any good.

Alternatively, I could write a note that some script-driven browser is needed.

I am attaching my test script for reference:

require 'json'
require 'net/http'
require 'nokogiri'
require 'pry'
require 'uri'

uri = URI("https://www.ribose.com/login")
token_input_css = "form#new_user input[name=authenticity_token]"
meta_uri = URI("https://www.ribose.com/csrf_meta")

login_src = Net::HTTP.get(uri)
login_page = Nokogiri::HTML(login_src)
token = login_page.at_css(token_input_css)["value"]
puts "token is", token

token_meta = JSON::parse(Net::HTTP.get(meta_uri))["token"]

puts "meta token is", token

form_params = {
    "utf8" => "✓",
    "authenticity_token" => token_meta,
    "invitation_code" => "",
    "return_to" => "/wow",
    "user[username]" => "skalee@gmail.com",
    "user[password]" => "<password>",
    "user[remember_me]" => "1",
}

post_resp = Net::HTTP.post_form(uri, form_params)
puts "status code", post_resp.code
puts "redirects to", post_resp.header["Location"]
ronaldtse commented 7 years ago

@skalee you are absolutely correct. The current /login API actually provides you a "session cookie" on load, and when you have authenticated, it is the "session" in the cookie that is authenticated. A subsequent access must utilize the same "session cookie" to load to prevent the 403 error.

This is a problem in the current code that @ribose-jeffreylau is changing. In any case, the current usage of ribose-ruby is like this:

  1. Use username/password to login and authenticate session cookie.
  2. Use session cookie to fetch API token.
  3. Use API token (set in the header) for all subsequent requests. We don't need cookies once it has fetched the API token.

@ribose-jeffreylau please help fill in any missing bits. Thanks!

skalee commented 7 years ago

In this case I'll make a pull request with what I have now (wiki content translated to API Blueprint). I don't have write permissions in this repository though, could you fix, @ronaldtse?

ribose-jeffreylau commented 7 years ago

@skalee Just added you as a collaborator. Sorry about the omission earlier 😅

ribose-jeffreylau commented 7 years ago

@skalee

To use the API endpoints, we currently use our individual API tokens in the request headers which can be obtained this way.

Actually the way our Ribose-ruby client works, is that on first log-in (using email & password), it uses mechanize to log in using the login form and CSRF token, then it fetches and keeps the API token obtained from a JSON response (i.e. not from cookie) for use in subsequent requests, avoiding the need to use further CSRF tokens.

ribose-jeffreylau commented 7 years ago

Regarding pull requests, yes I do make them, they're just merged almost right away. Actually, I have been the only one who makes pull requests so far. We need everyone to make pull requests 😛

ribose-jeffreylau commented 7 years ago

@skalee Another thing that's slightly embarrassing is that fdff37f52bfdd485c08620c85ce7022caabe4c00 already did most of what this issue aims to do, except that the relevant section (logging in and out) should belong in the file user_session.apib. I'll leave this issue open until this is fixed.

Also, extra work on providing sample values is appreciated! See #19 for our on-going discussion on sample values.

Thanks! :)

skalee commented 7 years ago

BTW Regarding other documenting tasks, should I take them freely, even when they're assigned to someone else, or should I wait for assignment?

ronaldtse commented 7 years ago

@skalee it is much appreciated if you could take them on freely! Thanks!

skalee commented 7 years ago

Okay! Now I see that most recent tasks are unassigned, contrary to those from last week.

ronaldtse commented 7 years ago

Our goal is to fully document the API, so anything towards that goal is perfect :-)