Using Flask-Security Roles with Flask-JWT REST API - rest

I am building a Flask-based REST API and using Flask-JWT to handle JWT auth. I also want to use the built in roles management with Flask-Security. However, Flask-Security's #roles_required() decorator assumes I am showing a Flask view when it fails.
Here is my token endpoint (which is working as I want):
$ http POST localhost:5000/auth/token username='test' password='test'
HTTP/1.0 200 OK
Content-Length: 192
Content-Type: application/json
Date: Sun, 08 Nov 2015 17:45:46 GMT
Server: Werkzeug/0.10.4 Python/3.5.0
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ"
}
Here is a successful response to a resource that does not have any role requirement (using only #jwt_required) This is also working as I want:
$http GET localhost:5000/protected Authorization:'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ'
HTTP/1.0 200 OK
Content-Length: 25
Content-Type: text/html; charset=utf-8
Date: Sun, 08 Nov 2015 17:46:24 GMT
Server: Werkzeug/0.10.4 Python/3.5.0
<models.User[email=test]>
When I do the same for a resource that has roles required (such as admin in this example), it seems to assume I have a page to display such as /login which I do not since it is a headless REST API:
$ http GET localhost:5000/admin Authorization:'JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NDcwMDQ3NDYsIm5iZiI6MTQ0NzAwNDc0NiwiZXhwIjoxNDQ3MDA1MDQ2LCJpZGVudGl0eSI6MX0.RFIeaLuvJNM9fDjFYFQ7sh_WaDVU-_aM7e46tVJzlBQ'
HTTP/1.0 302 FOUND
Content-Length: 209
Content-Type: text/html; charset=utf-8
Date: Sun, 08 Nov 2015 17:46:43 GMT
Location: http://localhost:5000/
Server: Werkzeug/0.10.4 Python/3.5.0
Set-Cookie: session=eyJfZmxhc2hlcyI6W3siIHQiOlsiZXJyb3IiLCJZb3UgZG8gbm90IGhhdmUgcGVybWlzc2lvbiB0byB2aWV3IHRoaXMgcmVzb3VyY2UuIl19XX0.CSEcAw.pjwXLeSWUsORXR-OU5AfFvq6ESg; HttpOnly; Path=/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: /. If not click the link.
I know Flask-Security uses Flask-Principal behind the scene for its roles management (#roles_required, etc.) and it ties into the RoleMixin and UserMixin for the datastore which is very nice. However, if there is no way to get Flask-Security to just allow the resource through without using my JWT header, then maybe the best bet is to build my own decorators which uses Flask-Principal to manage the roles.
Does anyone have any experience with this? The idea is that the entire front end can and will be built in whatever language we need and that means it may not be Flask's templates/views which is what Flask-Security appears to be doing.
Thank you for any insight anyone can provide!

Instead of a redirect, you would want to respond with an HTTP status code 403.
Your best bet is indeed to create your own decorator to manage the roles, and move away from using Flask-Security entirely.
The author of Flask-Security has mentioned that there are better ways to secure APIs, and it makes even more sense as the library is not maintained.
Flask-JWT or Flask-JWT-Extended are perfect candidates for this task. The former would require a bit more boilerplate to get things going. There is a stale PR suggesting an API to support roles, that you could use to create your own decorator if you decide to go with Flask-JWT.
The Flask-JWT-Extended docs suggest a simpler solution that might fit your case. You should follow the custom decorators section of the documentation for the full example, but here's the decorator in the nutshell:
from functools import wraps
from flask import jsonify
from flask_jwt_extended import (
verify_jwt_in_request, get_jwt_claims
)
def admin_required(fn):
#wraps(fn)
def wrapper(*args, **kwargs):
verify_jwt_in_request()
claims = get_jwt_claims()
if claims['roles'] != 'admin':
return jsonify(msg='Admins only!'), 403
else:
return fn(*args, **kwargs)
return wrapper
This code looks for a roles claim in the JWT, and returns a 403 response if it is not admin.

Related

HTTPIE 307 Temp Redirect - APIGATEWAY

I'm trying to get an AWS APIGateway implementation going, and am trying to send a request from the HTTPie module rather than from Postman. It works perfectly from Postman, but HTTPie doesn't seem to work for me, and only throws a 307 Temporary Redirect.
Using the following command:
http POST {userid}.execute-api.ap-southeast-2.amazonaws.com/sqstest/message name=john
Outputs:
HTTP/1.1 307 Temporary Redirect
Connection: keep-alive
Content-Length: 185
Content-Type: text/html
Date: Mon, 16 Apr 2018 06:28:24 GMT
Location: https://{userid}.execute-api.ap-southeast-2.amazonaws.com/sqstest/message
Server: CloudFront
Via: ################(CloudFront)
X-Amz-Cf-Id: ######################
X-Cache: Redirect from cloudfront
I did notice that Content-Type was text/html, which was odd considering I needed to send a json - but no matter what variant of the command I tried, it would still return the same results.
From my understanding it should work the same as Postman as long as the headers are the same (they are minus the content-type, which doesn't change even if I define it using -j/--json).
Any help?
Cheers.
After a few hours of trial-and-error, determined that the error was in syntax.
Required a https:// on the command and to state it as json it needed a semicolon (:).
For example:
http POST https://{userid}.execute-api.ap-southeast-2.amazonaws.com/sqstest/message name:=john
As opposed to the statement in the question.

TFS Web Calling an external REST Service throws 401 error

When creating a web hook within TFS (to access an external rest service url), I get a 401 error when testing (within the TFS application). I think call is not hitting API at all.
Below is the response I can see
Status Code: 401
Reason Phrase: Unauthorized
HTTP Version: 1.1
Headers:
{
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-UA-Compatible: IE=EmulateIE8
Date: Fri, 30 Mar 2018 21:05:26 GMT
Content-Length: 1293
Content-Type: text/html
}
Any help would be appreciated!
The error ID 401 usually related to the authorization.
You could first use postman to double check user ID access to the API.
Also use week hook to access some other rest service url such as the example in Web Hooks. This will narrow down if the issue related to rest service url.
Besides try to use Basic Authentication, you can use alternate account instead. How to please take a look at:Protecting a VSTS Web Hook with Basic Authentication

How to login to RQM using REST API?

I'm trying to communicate with IBM Rational Quality Manager server using its REST API. I'm using RESTClient browser plugin, and while the browser is logged in, everything works as expected. For the record, my requests look like
https://server/qm/service/com.ibm.rqm.integration.service.IIntegrationService/resources/project/testscript/urn:com.ibm.rqm:testscript:42
However, if I wait long enough for RQM to logout, REST API says I need to login back to proceed (see below). I'm pretty sure this is possible to do via the API itself, because RQM ships with RQMUrlUtility which accepts username and password and runs basically the same REST requests I'm using:
java -jar RQMUrlUtility.jar -command GET -user JazzUserID -password JazzPassword -filepath pathtoFile -url REST_URL
So far, I have found this topic explaining how to login using HTTP basic authentication. Following this advice, I have added Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= (not my real password) to the request, but RQM still fails to login. I have also tried setting User-Agent to a bogus value, as well as sending the value from JSESSIONID in X-Jazz-CSRF-Prevent header as described here, but regardless of all these headers being present or not, I get the same response:
Status Code: 200 OK
Cache-Control: no-cache="set-cookie, set-cookie2"
Connection: Keep-Alive
Content-Encoding: gzip
Content-Language: en-US
Content-Type: text/html; charset=UTF-8
Date: Tue, 26 Jan 2016 15:48:02 GMT
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Keep-Alive: timeout=10, max=100
Set-Cookie: JazzFormAuth=Form; Path=/qm; Secure
x-com-ibm-team-scenario=ac55f959-c738-4ef0-854d-6e37648edcba%3Bname%3DInitial+Page+Load%3Bextras%3D%2Fqm%2Fauth%2Fauthrequired%2C1453823282026; Path=/
Transfer-Encoding: chunked
X-Powered-By: Servlet/3.0
X-com-ibm-team-repository-web-auth-msg: authrequired
Can anyone with experience with RQM API tell me what's wrong? Or perhaps I'm missing something basic, common to most RESP APIs out there?
Could it be your header name?
Authorisation: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Should probably be:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Notice the "z".

CAS set-up using restlet API to secure REST services

I was trying to use it for Single sing on. I was able to successfully secure my web services/pages and want to extend it to my REST APIs (services) as well. I am using CAS 4.0.0.
I followed this link http://jasig.github.io/cas/4.0.0/protocol/REST-Protocol.html and change the web.xml as suggested and added the following jar to my CAS deployment WEB-INF/lib folder:
cas-server-integration-restlet-4.0.0.jar
org.restlet.jar
org.restlet.ext.spring.jar
org.restlet.ext.servlet.jar
The Call to the "v1/tickets" is reaching the restlet-frame work but I am getting a 404 error to my rest client
Status Code: 404 Not Found
Accept-Ranges: bytes
Content-Length: 439
Content-Type: text/html;charset=UTF-8
Date: Thu, 06 Nov 2014 13:12:46 GMT
Server: Restlet-Framework/2.2.2
Can you Please help me identify the issue with the set-up or point me to a detailed documentation.
Disclaimer: I'm the Chairman of CAS and founder of CAS in the cloud (https://www.casinthecloud.com).
The endpoint is in lower-case: can you try: /v1/tickets?

What is `ff.im`?

When we visit fm.im, we are redirected to http://friendfeed.com.
Here are some other examples:
ff.im/abc
ff.im/efg
How is FriendFeed able to do this?
.im is the Isle of Man top-level domain (ccTLD). The registry normally requires names to be at least three characters long, unless you pay considerably more.
Two-character domains look cool but aren't particularly useful since IE rejects their cookies (old article, but still mostly true for newer IE versions).
When your browser requests ff.im:
GET / HTTP/1.1
host: ff.im
their webserver responds with a redirect, either to the main FriendFeed site:
HTTP/1.1 302 Found
Date: Sat, 09 Apr 2011 12:29:38 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Content-Length: 0
Location: http://friendfeed.com/
Server: FriendFeedServer/0.1
or to some other place (when using their URL-shortener).