Securing REST API for single page JS app? - rest

I'm interested in developing a RESTful JSON data API using Sinatra, and have an HTML5/JS app consume that data API. Obviously the data API needs some form of authentication so that user Joe can only access his own stuff via the API. It would be nice if I could not roll my own authentication, and instead rely on Google/Facebook/Twitter to be the identity provider.
I've looked into OAuth2 using Omniauth and I can wire that up easily enough for traditional web apps, but when talking about securing the JSON API using FB/Twitter/Google, my understanding breaks down because:
The API shouldn't really be the thing doing the redirects for the OAuth2 flow, should it?
When the callback data from an identity provider comes through, it'd probably hit the HTML/JS app, right?
A further kink would be if I ever wanted to provide 3rd party developers API access via non-web mechanisms; the OAuth2 redirect flow business certainly wouldn't work here.
So all told, I'd have an architecture that looks like this:
[ HTML/JS client ] --- [ JSON API ] [ FB/Twitter/Google ]
|
|
[ Developer ]
In effect, what I'm after is what's here, except this is for Rails only:
sso-devise-omniauth-provider
Any pointers for doing this with Sinatra? Please use some specific examples.

Well you've sort of painted yourself into a corner. One premise of OAuth authentication is that there is a user who will take an action in an HTTP client (such as a web browser) to authenticate himself to the OAuth provider. If you want to provide 3rd party developers API access via non-web mechanisms then you cannot use that sort of authentication flow.
You need to follow the API Key pattern if you want to authenticate API clients that are not amenable to the interactive web-based authentication patterns. Somehow you need to generate API keys and hand them out to authorized 3rd party developers. Look at how Twitter, Facebook, and Google do it.

Related

Authentication via REST in Apache Shiro

I would like to enable authentication using a REST (preferably POST) call in Apache Shiro. The reason I want to use a REST call is so that both a web and mobile app, as well as a 3rd party using my API can use the same authentication call, which if true would pass back 200 and a token, which would then be used as a query (or form) parameter to authenticate the next call.
Can Shiro support the above described model? I am still evaluating Shiro and learning about it.
I have used some other authentication frameworks but they required that their login page in HTML be used to obtain authentication and I didn't like that because it eliminates mobile and 3rd party use.
For third-party API use cases, you probably want to use an OAuth flow:
Illustrated Guide to OAuth & OIDC
Shiro can act as the "Resource Server", see:
https://developer.okta.com/blog/2020/05/11/java-shiro-oauth
Full disclosure, I work at Okta, and the above link is Okta specific but you could do something similar with another IdP like Keycloak.

How to authenticate and authorize a user in username/password and google sign in?

The architecture of the system is like this
User can log into the website using either username-password approach (after registration) or a google-sign-in.
I want to know how can I implement authentication and authorization for this scenario.
Here is what I am thinking of implementing :
Have an REST API server built over NodeJS and Express.
The login and registration processes are handled by this server as well.
The authentication is done by using JWT Tokens stored in the client side. And these tokens are then used again for authorization of endpoints as well.
How much secure is this approach? And how can google sign in be added to this architecture.
And also if a seperate server for making auth requests is needed as mentioned in OAuth 2.0?
It would be better if the system remains Stateless to follow the principles of RESTFul APIs.
This post that I have written might give you some insight.
https://dev.to/ralphwjz/login-management-for-spa-and-everyone-else-12o6
The post covers Github login but if you replace GitHub with google, the rest of the flow is exactly the same.
I can answer more questions once in context

Securing an API called by the end users of a client

I am building an API meant to be sold to various clients. These clients will be given an API Key or something similar and they'll use the API in a widget on their website.
The end users of the clients' website must be able to use the widget anonymously (no login).
Workflow:
My current idea is to have the Client's server retrieve a temporary key and use that in the webpage. The End user's browser will use that temporary key to call our API.
Is there any reason why this is not a good practice and/or insecure?
Or is there a better good practice solution? Can I for exmaple use OAuth 2 for this?
You need to secure your API from the clients app. So, for that you can use OAuth 2 with Client Credentials grant type and setup each client as an app so they each get their own set of key/secret credentials.
Since you don't know anything about the end user, but still need to track them, require an endUserId custom header on every request to your API and you'll just have to trust the client to provide you with a valid id for the end user making the request.
To setup OAuth, use an existing library or OAuth service. I don't recommend writing your own. If you can spend some money, Okta and Auth0 are good choices. If your API is written in .net, you can use IdentityServer as a free option.

Authentication with Akka-Http

We're developing an iOS app, where the user needs to authenticate using email+password (or mobile number). Our backend is made of a couple of microservices using Akka-Http. It needs to be fast, scalable, concurrent, and the authentication+authorization should work across our multiple services.
I'm trying to figure out which authentication method to use.
Akka-HTTP currently offers Basic Auth and a partial implementation of OAuth2.
So at first we were considering Basic authentication (too simple and not enough functionality), Oauth1 (too complex), so we moved towards OAuth-2.0 because it is sort of a standard.
Then we considered AWS Cognito because it combines Oauth-2.0 and OpenID Connect which gives the authentication mechanism that OAuth2 lacks.
http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html
Then we realised that OAuth2 is just for authentication using a third party - when in fact we don't need a third party authentication provider - maybe we need to do it ourselves, and using Cognito is an overkill that would create extra api calls outside our microservices...
So I read a little bit about creating our own custom auth provider, using WSSE specs:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
And I also found this example using Spray, but I'm sure it's not that different from Akka-Http:
http://danielasfregola.com/2015/06/29/how-to-create-a-spray-custom-authenticator/
It looks too simplified and doesn't have token expiration...
So my question is, am I missing something? What method should I chose and where can I find examples for it?
I feel like I'm going in circles, we're gonna have to write our own custom authentication provider from scratch, which kinda doesn't make sense. After all almost everybody needs authentication and it should be a standard.
I've recently been using SoftwareMill's akka-http-session library and found it simple and easy to integrate. It has support for case class based sessions, JWTs, refresh tokens with pluggable storage, using headers and CSRF tokens as well as some nice simple directives for use in routes.
My solution for user registration has been to use Keycloak, an open source server which can handle user registration and do OIDC, OAuth2 style login. It reduces the amount of code I have to write, and the code is more secure than if it rolled it myself.
I then write my application as Scala backend that's purely a JSON API and a React/Javascript rich frontend in front of that API. In this configuration the authentication is handled completely on the front-end (and can be done in your iOS client). The front-end app redirects the user to Keycloak and when the user comes back they have a signed "JWT" token you can keep in a cookie.
That JWT token is attached to all API calls made the JSON backend as an Authorization Bearer token HTTP header. The token itself contains the users email address and is cryptographically signed by the Keycloak server.
The backend gets the JWT token in the HTTP header, extracts the email address and verifies the token is cryptographically signed by the keycloak server.
It's performing a certificate check on the keycloak server and can cache it's certificate. So it doesn't need to have roundtrips like OAuth, or any upstream calls to make.
This gives us simple, low-chance-of-failure, high speed authorisation in our JSON backend API and means we aren't putting secrets in the iOS client, or rolling too much of our own code.

Securing a REST API consumed from Ajax and mobile apps and 3rd party developers

I have am writing a REST API (using ASP.NET WebApi) and it will be used by my single page web app via client side JavaScript calls mobile apps that anyone can install and eventually I would like it to be used by thirst party developers to write their own apps.
I have looked into HMAC to secure the API but not sure how to get the private key onto the clients securely (I.e. browser client side, on mobile app?
I am trying to make it so only my apps, the 3rd party dev apps and my client side JavaScript can access the api.
In your use case, I would use two different authentication mechanisms. For the SPA running in the browser, I would authenticate the users using forms authentication, and I would rely on ASP.NET to validate the credentials stored in the cookie when the browser makes a call to the Web API using AJAX. For the third party or mobile apps, I would use HMAC authentication. You can exchange that key out of band as many of the cloud providers like Windows Azure or AWS do. I created an implementation of HMAC for Web API that you can use. It's available here,
https://github.com/pcibraro/hawknet
You can also exchange the key using SSL on the first call when the user is authenticated with username and password, but that's up to you.
Regards
Pablo