I am exposing a webservice using eventmachine and evma_httpserver as follows:
EM.run{
puts "Query Server running on port 9000"
EM.start_server '0.0.0.0', 9000, QueryEngineHttpServer
}
I would like to make it secure, i.e., require a user name and password. I know how to do this using Sinatra, but I'm not using it for this, so I'm no sure how to proceed.
which kind of authentication do you need? Basic-auth or cookie based?
is this something that can help you ?
module QueryEngineHttpServer
include EM::HttpServer
def post_init
# if you want the connection to be encrypted with ssl
start_tls({:private_key_file => path_to_key_file,
:cert_chain_file => path_to_key_file,
:verify_peer => false})
# don't forget to call super here !
super
end
def process_http_request
# Block which fulfills the request (generate the data)
operation = proc do
# depending of which kind of auth you want you should have to parse the cookie or the 'autorization' header
auth = check_for_auth #http_cookie, #http_headers
# create the response object to be used in the EM::defer callback
resp = EM::DelegatedHttpResponse.new(self)
resp.status = auth ? 200 : 401
resp.content = 'some content here...'
resp
end
# Block which fulfills the reply (send back the data to the client)
response = proc do |reply|
reply.send_response
end
# Let the thread pool handle request
EM.defer(operation, response)
end
end
Related
I am able to get the jwt token for the get, post, put requests using **get_jwt_identity()*.
But how can i acquire it for flask-sockets.
def handle_message():
emit('message_activated', {'data': 'my data', 'count': 0})
socketio.on_event('message', handle_message)
Assuming you are using the JavaScript Socket.IO client, you can use the extraHeaders option to pass custom headers. Example:
var socket = io("http://localhost:5000", {
extraHeaders: {
"X-My-Auth": "your-token-here"
}
});
Of course you can replace the X-My-Auth header name with the header that you are using.
In the server, authentication for Flask-SocketIO events is performed only when the client connects. There is no need to authenticate every single event because there is a permanent connection between the client and the server. Here is an example connection handler:
#socketio.event
def connect():
token = request.headers['X-My-Auth']
if not verify_token(token):
return False
# user is authenticated, proceed normally from here on
I'm getting the error
Access to fetch at 'http://hpap-dev.pmacs.upenn.edu:5801/get-categories' from origin 'http://hpap-dev.pmacs.upenn.edu:5802' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
despite using flask_cors. My flask app and route look like this
#Start flask app
app = Flask(__name__)
#Open flask for querying from domains outside of the app
CORS(app)
<snip>
#app.route('/get-categories')
#cross_origin()
def get_categories():
frame_dict = file_cat_wrangle.get_wrangle_dict()
# orig
# return jsonify(response=frame_dict)
# stauffer - try this to resolve CORS problem
response = jsonify(response=frame_dict)
response.headers.add('Access-Control-Allow-Origin', '*')
return response
As you can see, the code's calling CORS(app) as well as #cross_origin() under the route. And I also tried adding the Access-Control-Allow-Origin header explicitly to the response, per another stackoverflow post.
I've rebuilt and restarted the flask server. AFAIK this used to work on this server (I've taken over this project at work and am pretty new to web dev). Other API calls that go between the front-end (node server) and back-end (the flask app) are working. I also checked that the route path and the call to it are identical.
Here's the call from the front end:
export const fetchCategories = () => {
return fetch(`${flask_url}/get-categories`)
.then(response => {
if (response.status >= 400) {
throw new Error(`${response.status}: ${response.statusText}`);
}
return response.json();
}).then(categories => categories);
}
Any suggestions??
Check if the header is really present in the network tab in your browser.
You can use hooks to enable cors as below:
#app.after_request
def after_request(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
Turns out it was not actually a CORS-related error but some kind of odd error response. See my comment to the original question.
this is my first time using Google API, and i got difficulty about google-people api, can anybody here explain what needed header/body data for auth (i use https://crystal-lang.org/api/latest/OAuth2.html), and please share a simple code (vanilla / without library) in your favorite programming language ^^
Follow steps described in Get Ready to Use the People API. There you will find examples written in Java, Python, PHP, .NET.
Let's assume you finished with step 1 and 2. Here is a Crystal code to make an authorization request:
require "oauth2"
client_id = "CLIENT_ID"
client_secret = "CLIENT_SECRET"
scope = "profile"
redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
client = OAuth2::Client.new(
"accounts.google.com",
client_id,
client_secret,
authorize_uri: "/o/oauth2/v2/auth",
redirect_uri: redirect_uri
)
authorize_uri = client.get_authorize_uri(scope)
authorize_uri #=> https://accounts.google.com/o/oauth2/v2/auth?client_id=CLIENT_ID&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcontacts.readonly
Open authorize link in your browser, allow access to your data and you will get a token required for the next step.
authorization_code = code # authorization code taken from the previous step
client = OAuth2::Client.new(
"www.googleapis.com",
client_id,
client_secret,
token_uri: "/oauth2/v4/token",
redirect_uri: redirect_uri
)
access_token = client.get_access_token_using_authorization_code(authorization_code)
client = HTTP::Client.new("people.googleapis.com", tls: true)
access_token.authenticate(client)
response = client.get "/v1/people/me?personFields=names"
response.body # a json that contains my name
So I am using doorkeeper in my Rails 4 app and built an API wrapper for it to help my ruby users out. Almost everything works the way it's supposed to. I added an OAuth2 client that looks like this:
require 'oauth2-client'
module MyApiWrapper
class OAuth2Client < OAuth2Client::Client
SITE_URL = 'https://myapp.com'
TOKEN_PATH = '/oauth/token'
AUTHORIZE_PATH = '/oauth/authorize'
def initialize(client_id, client_secret, opts={})
site_url = opts.delete(:site_url) || SITE_URL
opts[:token_path] ||= TOKEN_PATH
opts[:authorize_path] ||= AUTHORIZE_PATH
super(site_url, client_id, client_secret, opts)
yield self if block_given?
self
end
...
def refresh!(token, opts={})
opts[:authenticate] = :body
refresh_token.get_token(token, opts)
end
end
end
When I first create an instance of the OAuth2Client and authorize a user it looks like this:
client = MyApiWrapper::OAuth2Client.new(ENV['CLIENT_ID'], ENV['CLIENT_SECRET'])
response = client.exchange_auth_code_for_token(:params => {
:code => params[:code],
:redirect_uri => 'http://localhost:3000/auth/myapp/callback'
})
token = JSON.parse response.body
access_token = token["access_token"]
#refresh_token = token["refresh_token"]
It responds with a token pair (with the refresh_token) the way that it's supposed to. Using that same OAuth2Client instance as before, I can successfully refresh the token in order to get a new token pair, like so:
response = client.refresh!(#refresh_token)
However, if I try to do the same thing with a new instance of an OAuth2Client (at a later time or in another controller, etc.) then I get the following error response from doorkeeper:
The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.
I am currently developing a web app which should do restful service calls to existing web service api.
What I have is the base URL and the API names.
Any help on how do I start working on it?
I suppose I need to use httpbuilder for the base url I have, then followed by /api name. But how do I test it on grails if its working?
When I paste the base url on the browser it does return some xml information, so what I need is to do it on grails instead.
XML response when I paste the url through browser
<ns1:createNewUserResponse>
<userId>21</userId>
</ns1:createNewUserResponse>
So I need to be able to get this response through my web-app (grails) instead of pasting it on the browser.
EDIT*
this is a good example I found useful
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.0-RC2' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def http = new HTTPBuilder( 'http://ajax.googleapis.com' )
// perform a GET request, expecting JSON response data
http.request( GET, JSON ) {
uri.path = '/ajax/services/search/web'
uri.query = [ v:'1.0', q: 'Calvin and Hobbes' ]
headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4'
// response handler for a success response code:
response.success = { resp, json ->
println resp.statusLine
// parse the JSON response object:
json.responseData.results.each {
println " ${it.titleNoFormatting} : ${it.visibleUrl}"
}
}
// handler for any failure status code:
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
}
}
but i do not understand the query part and how do I alter it to my need?
the URL I have contains credential of username and password, the response should return a securityToken which I need to get it out from the results. Any help would be greatly appreciated!
You can start with groovy-wslite, it provides both SOAP and REST webservice clients.
To make a call to a resfull service look at Groovy HttpBuidler - http://groovy.codehaus.org/HTTP+Builder