# typed: true require 'socket' module Tide module API # Receives an authorization grant code from the OAuth2 callback. class AuthServer # This is the ID shown in the authorization page of the mobile app CLIENT_ID = 'tide-api-gem'.freeze # Complete HTTP response RESPONSE = "HTTP/1.1 200 OK\r\n" \ "Content-Type: text/plain\r\n" \ "Content-Length: 31\r\n" \ "Connection: close\r\n" \ "\r\n" \ "You can now close this window.\n".freeze def initialize @server = TCPServer.new('localhost', 0) @port = server.addr[1] end # Runs a tiny HTTP server to receive OAuth2 callbacks. # # @return [String] The authentication grant code from Tide. # def run puts 'Waiting for the authorization code...' request_auth_nonce socket = server.accept auth_nonce = extract_auth_nonce(socket.gets) puts 'Authorization code received.' socket.print RESPONSE socket.close auth_nonce end private # @api private def request_auth_nonce system("open '#{auth_page_url}'") end # @api private def redirect_url "http://localhost:#{port}&client_id=#{CLIENT_ID}" end # @api private def auth_page_url "https://api.tide.co/tide-backend/oauth/index.html?redirect_url=#{redirect_url}" end # @api private def extract_auth_nonce(http_response_line) http_response_line.split('=').last.split.first end # @api private attr_reader :server, :port end end end