How to allow only my SPA to call my public rest API? - angularjs

I've a SPA (Angular based) published at my-example-domain.com and rest API (based on Laravel 5.3), exposed at my-example-domain.com/api.
All API are public, so unauthenticated user can use my Angular SPA and call backend API.
I would like to allow ONLY my SPA to call my backend rest API so, for example, nobody should be able to call my rest APIs through a rest client/curl.
How can I reach this goal?
What kind of authentication should I have to set up in my Laravel app?
Is Passport the right way?

You can't.
Your client is available to the public.
It runs in a browser, so all the HTTP requests it makes can be inspected by its users (i.e. everyone).
Anything you do to try to identify the request as coming from your client, can be inspected and replicated by anyone.

Related

Is it safe to have a frontend button that links directly to backend?

I am creating a full stack application with a React/TS frontend and FastAPI Python backend both on different domains/origins. For my first API endpoint (an auth endpoint), I cannot use axios.get(/login) as I planned as I'm using a 3rd party API in my backend that doesn't work with redirects to my frontend. The solution seems to be to have a login button with an a tag that directly links to http://backend_url/login. This does work, but it feels weird/unsafe to literally send users on the frontend to the literal url of my backend as opposed to just calling HTTP requests to the backend. Is this bad practice? Is there a better way to accomplish this? I appreciate any direction.
The question is more on how to deal with a 3rd party API that a user needs to authorize, see comments on OP.
You can redirect directly from your frontend to the /authorize endpoint of Spotify. They will call the returnUrl that you gave when you registered your application with them, and provide a authorization code. If this is in your frontend (e.g. http://frontend.com/oauth/callback, that can take that authorization code and feeds it to your backend (for example, to http://backend/api/auth). That endpoint can exchange the authorization code for access tokens (calling the /token endpoint of Spotify, of something similar) using the client credentials that you received when you registered your application with Spotify. The backend can store and use those access tokens, and your frontend can call the backend.

JWT for Public .Net Core WebAPI

I am thinking of using a JWT to secure my .net Core WebAPI endpoints for a public API. This API will only be consumed by a React front end that does not require a user to authenticate. I am trying to ensure that only my React app can call my WebAPI endpoints.
My thought is to include the JWT when the React app is downloaded/initialized and use it when calling the API.
Thoughts on this? Are there other more efficient ways to do this?
My thought is to include the JWT when the React app is downloaded/initialized and use it when calling the API.
I guess that way wouldn't work because I can copy the JWT token/API-Key or whatelse from network easily and use it for sending own requests. If your API is setup well (validation etc.), sending requests "manually" shouldn't be a problem. So why you only want your react app to request your app?
The only way (I guess) to give only your react app access to the API is to configure your API-server/proxy to accept only requests from the same domain.

Azure AD implementation for SPA / WebAPI application having both on the port/HostEnv.?

I am trying to implement Azure AD authentication in a SPA application.
I am using an OWIN Startup.cs file in the WEB API and ADAL.js file in the angularjs front end application. (as per most of the tutorials suggestion)
My application does not have WebAPI and UI hosted in different domains/port. Basically, the WebAPI is referenced in the UI application project. (So no need for enabling CORS).
Now I have registered the applications on the Azure AD separately.
i.e. ClientApp -> Reply URL: http://localhost:90/ and
WebAPI -> APPID SignOn URL: http://localhost:90/Api/V1/
I have configured the ADAL.js and also getting the login page when trying to access the application from the UI. Also, I am able to retrieve the id.token generated after logging through the URL redirection. Also have decorated the web api controllers with the [Authorize] attribute.
My main concern here is that, if I try to call the WebAPI directly using tools like postman, I am getting access denied/Unauthroized Access (401). Can someone pls explain how can I test on my local env. with this scenario?
My sample request is: http://localhost:93/Api/V1/User/Preference (GET)
I am adding the token in the Authroization property of the Headers in the web api call.
Also a side note, I don't think I require OWIN/Startup.cs file for securing the WebAPI. The way I tried is that I got the token value send through the headers and got the AudienceID using JwtSecurityToken and parsing the contents of the Authroization property. Is this approach right as per security or I should stick to the OWIN implementation.
All of the ADAL JS tutorials have the backend API and the UX hosted on the same domain and port, with no need for CORS. See for example https://azure.microsoft.com/en-us/resources/samples/active-directory-javascript-singlepageapp-dotnet-webapi/. Those samples demonstrate that you need only ONE Azure AD registration, as the JS layer is in effect the exact same app as the web API.
We do have some samples demonstrating how to call an external API as well, and those do require CORS- but only for the extra API. The logic for calling the app backend remains the same (just one Azure AD app registration, no need for CORS).Postman doesn't offer any opportunity to pop out UX, hence one strategy you can follow is to obtain the tokens you need beforehand.
The use of OWIN allows you to centralize the auth setup; if you add auth in the controller, you'll need to repeat that logic for every new controller you add. Also, maintaining the code will be harder as you might use API surface that requires code changes when you update the assemblies, while that's less likely to happen if you use the standard middleware setup

AngularJs + Rest Backend CSRF Security

I am building a simple AngularJs web app that hits a REST Api built with Flask. From what I understand, there are a few ways to protect against CSRF, one of which is sending back a CSRF token when the user authenticates.
If I wanted to make my API available to both the Web Application and to users who want to use it as an API for development, would I need 2 endpoints for each endpoint that allows POST requests [one for the app that requires CSRF token + auth token and one for the developers that requires just an api access key]?
Not necessarily. Broadly, you have two options:
Proxy the REST API through whatever server-side container your web app is running in. Your web-app proxy can then implement the CSRF protection and insert the API-key into the API request.
Check the referrer header on all API requests. Although this requires that your Angular SPA and API share the same authentication mechanism, so you'd have to use something more sophisticated than an API key, like OAuth.

Oauth social login using MEAN.js Restful sessionless API backend

I'm developing a Restful API using MEAN.js, which will be consumed by an AngularJS Web site and Phonegap Mobile Apps.
I'd like the user to be able to create an account and/or login using Faceboo, Google and Twitter.
I'm trying to use the same sample code that comes with MEAN.js seed application, but with the Node side of it, on port 3000 serving only the API, and the web site running on another server (currently on port 9000).
I','ve already implemented Token authentication using a Passport custom Local strategy, which generates a token, and the Bearer Strategy to autheticate API calls.
But I'm having problems with social login, to link social accounts to existing users.
From the Angular Client I call an api endpoint that redirects the user to the oauth provider (e.g. Twitter). When the user comes back, my serve has no knowledge of the logged user, since I'm not using sessions anymore.
I've tried to return the provider token to the client, but have problems parsing the anguler url. Then I coded another page outside angular that receives the provider token and calls an api endpoint sending the oauth token and the token issued by my api. It worked for Google, but not for Twitter. It seems twitter needs a session.
Anyway, what is the best approach to achieve what I want? How can I make this work?
Since your using Angularjs, take a look at this Angularjs library https://github.com/sahat/satellizer. The library pretty much opens up an oauth popup and checks the popup url for tokens. You can easily replicate the approach or just use this library. It works with a few social media providers like Twitter and its easy to add more.
I was in need of the same thing and so I set out to create my own. It's still in development but should give you a good start. Feel free to create a pull request and help to make it better. Maybe we can eventually merge it into their codebase.
https://github.com/elliottross23/MeanJsSocialLoginTokenAuth

Resources