Authentication and Authorization modules that don’t
encapsulate the credentials in one piece such as a token suffer from the
problem that they are just about as secure as SMTP. Anyone can spoof anyone by
passing different user ids. That said there is a real need to be able to switch
users in the request.user such that an API implementation can be tested and
have very little or no instrumentation for the live usage by a logged in user
as well as for the passive testing for coverage. The latter can possibly be
alleviated with test accounts that are created beforehand for all API
implementations. Such a test account may need to be registered in the Active
Directory as a user that can sign in. This may or may not be available. On the
other hand, when user information in the
passed credentials are hardened, then they become tamper proof and push the
switching to using different tokens.
With the above two requirements in a landscape with a
typical portal or WebUI accessing different API functionalities through a gateway,
we now look at the minimal steps or changes required to merely use the token
and nothing else for authentication providing a one-point maintenance and hence
secure switching. Each request is therefore authenticated and the sessions is
guaranteed for the lifetime of the token.
Django-oauth-toolkit 0.9.0 package https://pypi.python.org/pypi/django-oauth-toolkit
provides all the implementations for an RFC compliant OAuth server. By definition
of OAuth, when users accept certain applications to access some or all of their
information, they enable the OAuth server to cut tokens that represent the
user+client+the-issuing-authority. The token can then be passed directly in the
Authorization header or in its own custom header or as query string whichever
is convenient. The application can be a
web portal and will have its own client id and client secret. When a user logs
in to the portal, she blesses certain modules aka clients. These modules can in
turn request token from an OAuth server.
Ideally, the identity provider such as Okta will implement the Oauth
token server itself and hence we could use those OAuth APIs as priority. In the absence of these OAuth
apis, we write an OAuth server but don’t put it behind the Nginx server that
forwards to different destinations. Since the clients are registered in a table and the users are also registered,
the OAuth server does not need to verify the requestor to issue the token.
Besides, the verification of the token requestor is handled within the
protocol.
The first step therefore it to use an OAuth server such as
the out-of-box OAuth server with the toolkit referred above and deploy it
outside the gateway to different API functionalities.
Second the portal needs to provision a page that lets
clients be registered. Note that a developer who writes a client application is
the user who logs in to access this page. Clients may be written by one user (owner/developer)
and request the server for tokens on behalf of the users of the client. This
page has captures the information such as the name, description, callback URL
and environment.
Third the portal needs to provision a page that lets logged
in users to permit different clients to request tokens from the OAuth server on
their behalf. This page usually has the description of the client and the kind of
information it will be accessing from the users profile. In addition, it may
disclose all the actions it will take the user’s information.
Fourth, the use of a utility package to verify the token
employs a static method (one that relies entirely on the parameters passed in
and does not have an instance associated for any API implementation) that takes
a request header and validates it against the OAuth server. Given a token, an OAuth server can reverse
lookup the associated user, client and check itself as the issuing authority.
The method returns this looked up information.
Finally, the API implementations should have the ability to
get information such as
Request.user.id
Request.user.email
Request.user.fullname
And arguably request.user.password (encrypted)
With these an API should be able to impersonate the logged
in user.
No comments:
Post a Comment