# Copyright 2000-2014 NeuStar, Inc. All rights reserved. # NeuStar, the Neustar logo and related names and logos are registered # trademarks, service marks or tradenames of NeuStar, Inc. All other # product names, company names, marks, logos and symbols may be trademarks # of their respective owners. module Ultradns::Api::Authentication # Try a request and if there is an authentication failure, retry after # refreshing the tokens. # # yields to the block with the class so that HTTParty class methods can be used. # Example: with_auth_retry {|c| c.get '/' } def with_auth_retry(&block) retries = 3 response = nil while retries > 0 response = yield(self.class) if auth_failure?(response) refresh retries = retries - 1 logger.info "authentication failure, retrying..." if retries > 0 else retries = 0 end end response end def auth_failure?(response) error_code = response.parsed_response["errorCode"] rescue nil (response.code == 400 || response.code == 401) && error_code == 60001 end def add_auth_header!(params) refresh if params[:force_refresh] (params[:headers] ||= {})['Authorization'] = "Bearer #{access_token}" params end def auth(username, password, base_uri) @auth = {} @auth[:requested_at] = Time.now.to_i response = self.class.post('/authorization/token', body: { grant_type: 'password', username: username, password: password }, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' }, base_uri: base_uri ) body = response.parsed_response logger.debug "Auth Response: #{response.inspect}" raise "Authentication Error: #{response.body}" unless response.code == 200 # temp @auth[:username] = username @auth[:password] = password @auth[:base_url] = base_uri @auth[:access_token] = body['accessToken'] @auth[:refresh_token] = body['refreshToken'] @auth[:expires_in] = body['expiresIn'] end def no_expiry? # no expires provided yet - TBD @auth[:expires_in] == nil || @auth[:expires_in] == '' end def refresh? (@auth[:requested_at] + @auth[:expires_in]) >= Time.now.to_i end def refresh # expires not available, then reauth return auth(@auth[:username], @auth[:password], @auth[:base_url]) if no_expiry? # not expired yet. return unless refresh? requested_at = Time.now.to_i response = @client.post('/authorization/token') do |request| request.params[:grant_type] = 'refresh_token' request.params[:refreshToken] = @auth[:refresh_token] end logger.debug "Auth Refresh Response: #{response.inspect}" raise "Token Refresh Error: #{response.body}" unless response.code == 200 body = response.parsed_response @auth.clear # reset everything @auth[:requested_at] = requested_at @auth[:access_token] = body['accessToken'] @auth[:refresh_token] = body['refreshToken'] @auth[:expires_in] = body['expiresIn'] end def access_token @auth[:access_token] end end