2

I have web application which structure is as-

  • webapi : django web services [NOT REST] no security implemented
  • frontend : Angular2. authentication implemented via SAML
  • Database : Mongodb

Can you please suggest best way to secure webapi, as currently anyone can access web services who has server[api] url

It will be big help if you suggest the authentication and authorization flow because I am totally stuck. Thanks in advance.

sachin27
  • 31
  • 5
  • 1
    how have you done SAML 'client side'? – Ewan Dec 07 '17 at 17:07
  • we are using spring saml security at client side application, so when first user access web app url it will redirect to spring saml app which is hosted at same place where angular app is present, then after authentication spring saml app passes saml response which includes token and other claims such user basic info configured at active directory to angular app. After this angular app passes these details in request body to web service api which is hosted at different server. – sachin27 Dec 07 '17 at 17:19
  • thats server side authentication. your only problem is having the api on a seperate server. can it not validate the saml token? – Ewan Dec 07 '17 at 17:21
  • The problem is there is no security at web service api backend. There is no way I can validate that request came is valid request. Even though token is sent by angular app, web service api don't have any gurantee that this is valid token. So I am looking for a way where web api can validate token or implement authentication server side. Still if authentication is implemented at server side how can api redirect to login page. Help me out. I am open to hear any suggestion which is best – sachin27 Dec 07 '17 at 17:29
  • 1
    how does the website itself validate subsequent requests after the first one? usually it will either check the token signature or check the session token with the auth server – Ewan Dec 07 '17 at 17:36
  • with session token – sachin27 Dec 07 '17 at 17:38
  • so why cant the webapi also use the session token? – Ewan Dec 07 '17 at 17:41
  • it is because web api is public, anyone can directly access it from anywhere with invalid token – sachin27 Dec 07 '17 at 17:44
  • yeah but why make it public? why not use the same auth as the website? – Ewan Dec 07 '17 at 19:03
  • Sorry, I forgot to mention, as these apps, client as well as Web API are hosted on two application services on azure. Web API has python environment and hosted on IIS server where as client web app (angular ) is hosted on tomcat server. There is also android and iOS mobile apps which are using same python web services. That is why Web API is kept separate – sachin27 Dec 07 '17 at 19:12

2 Answers2

1

That webapi without authentication is a security risk. As you are already using SAML look into the Wikipedia page as a starting point. On the graphic at the bottom your webapi is the service provider

Miyamoto Akira
  • 2,265
  • 16
  • 17
  • So, are you trying to say, saml authentication should have implemented at server[ web api] side instead of client side. – sachin27 Dec 07 '17 at 10:32
  • Yes. Anything front end is insecure because all the Js is exposed and anyone can play with it. You need all your backend systems to have a security layer – Miyamoto Akira Dec 07 '17 at 10:34
  • Considering my current scenario could there be any workaround which solves my purpose? or I must implement authentication at server side? – sachin27 Dec 07 '17 at 10:39
  • Also, authentication and authorisation are separate concerns. Sometimes they are conflated, but keep them in mind as separate systems. – Miyamoto Akira Dec 07 '17 at 10:39
  • You have to. No way around it. Because the other option is to have the webapi in a private network and the use a proxy api on a DMZ with the security layer. Which gives you the same but more complicated. – Miyamoto Akira Dec 07 '17 at 10:41
0

I'll describe two ways you can do this:

OAuth

I'd recommend you use OAuth for the web api. You do not have to replace the SAML authentication if you do not want (though it would be more consistent if you used OIDC for the application authorization).

Basically, you'd authenticate against your spring app via SAML then, when querying the web api, in the Authorization Request phase of the OAuth workflow, you'd implement the authorization server on the same server as your spring app so you can use the session context as authentication for the authorization request.

You should take a look here to get an introduction to OAuth. OAuth was designed (in part) to solve exactly this problem.

I realize this is short on OAuth details but there are lots of good examples/tutorials out there on how to do this. You just need to recognize that, in the protocol flow, your spring app would serve the role of Authorization Server and would implicitly provide Authorization Grants for the web api service for Authorization Requests originating from (SAML) authenticated clients.

Your app is what OAuth refers to as a single page app (no sever-based client). The flow for single page apps is described here. Essentially, your spring app will implement an OAuth Authorization Server, your Angular (in-browser) app will request an authorization code from your Authorization Server. If you want your user to approve access then you will create an approval page which describes what API actions they are approving. If you want this to be transparent, you would simply return the authorization code. Once your app has an authorization code, it immediately exchanges the code with the Authorization Server for an API access token.

Your Angular app would then query the API using the OAuth access token. The API receives the access token, validates that it is "good" then allows (or denies) access. You validate that the token is "good" either through a shared database with the Authorization Server (i.e. when the auth server creates a token, it stores it in the database for later validation by the API server) or by decoding a self-encoded token (basically the auth server and the api server share an encoding key and the token is an encoded string that has all the information the API needs to grant/deny access).

Roll-your-own

If OAuth is a bit too daunting (though it's arguably the Right Way to go here...) I've used a simple, home-grown authorization token scheme in the past as well.

In this case you design your web api to require an access token (provided by clients either in a header, qstring, or query payload). When authenticating the client app, your spring server will generate a token and send it back (securely via tls/ssl) to the client for use with the django web api. The token is encrypted with a shared (between the spring app and the django app) key and has a structure that the django app can grok (I usually include a timestamp to limit replay, username for local authorization, sometimes custom authorization information that the api can use instead of making local auth decisions). I'd also recommend you salt the message as well to make a plaintext attack of the token harder. Another option to limit replay is to make the tokens single use and to require a token fetch each time you make a query. And, finally, if you do use a timestamp (epoch integer seconds is convenient...) you'll need to make sure that your spring and django servers are (at least somewhat) in time sync.

Jim Culbert
  • 131
  • 3