Separate User / Admin API? - angularjs

I'm building a multi tenant app using Angular and Node.js, is it wise to have the same API for both Front End users (Public) and Admin Area users (Tenants)?
The Admin Area will require authentication for viewing and modifying sensitive data but I don't see why the rest of the API can't be left open for the front end which is only querying data?
Is this a good idea? Will it cause problems further down the line?
I'm looking to go for the following application structure:
Front end: tenant-name.domain.com (Open to public)
Admin area: domain.com/admin (with login and token auth)
API: api.domain.com
Would it be a good idea to have the client's front end authenticate with the API?

I would suggest that the admin area API calls require an auth token to be passed on all API calls. You can inject the token into the headers with http request interceptors in Angular. A user who does not already have an auth token should have to log in to get one. The injected auth token should be all the security you need.

I'll suggest you to create a token when an anonymous user requests your API. Reason for that is that you can always identify who requested what.

Related

Azure Active Directory - UI > API - 401 Error

Good Day,
Currently I have a single tenent with a React UI and .NET Core Apis secured by Azure Active Directory without any problems.
We have recently moved to a new Azure Tenent, new Active Directory etc. I have create two new App Registrations, one single App Service for UI and one for API. I have linked the App Service to AAD (UI = UI App Registration, API = API App Registration).
The problem is the API is getting a 401 error and I think see that in the original tenent the Bearer token is in a JWT format but in the new instance it's not, I believe it my be a graph api access key.
New Tenent:
Authorization: Bearer PAQABAAAAAAD--DLA3VO7QrddgJg7WevrQvEQVbZEMD8su-tIp9k2bTFUTort7SZgeDI52P6KRYefHgtmj4YrecgUKZJ2wylGuhvIzIz642n7Sg0VMU1RwKtrzWlaMqK62CaSoJcstxiEf6 *****
Orginal Tenent:
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyIsImtpZCI6Im5PbzNaRHJPRFhFSzFqS1doWHNsSFJfS1hFZyJ9.eyJhdWQiOiI3OThkN2ZkOC0zODk2LTQxOGMtOTQ0Ny0wNGFlNTQ2OGFkNDIiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83ZDE3NTU3Ni03Y2Y3LTQyMDctOTA5My0wNmNiNmQyZDIwNjAvIiwiaWF0IjoxNjE2NDUyNzExLCJuYmYiOjE2MTY0NTI3MTEsImV4cCI6MTYxNjQ1NjYxMSwiYWNyIjoiMSIsImFpbyI6IkFTUUEyLzhUQUFBQU9mejhPZHp *****
Please someone kindly enought to provide some guidance / input where I am going wrong.
Regards
Paul.
When using Azure AD to obtain an access token, an additional resource parameter is required. Otherwise, the access token is not a JWT.
For example, if your web API's application ID URI is https://contoso.com/api and the scope name is Employees.Read.All, then with oidc-client the client configuration should be :
scope: 'openid profile email Employees.Read.All',
extraQueryParams: {
resource: 'https://contoso.com/api'
}
In App Service auth configuration, you can use additionalLoginParams
"additionalLoginParams": ["response_type=code", "resource=https://contoso.com/api"]
If you did not use a custom application ID URI, it may look like
api://868662dd-3e28-4c7f-b7d5-7ec02ac9c601
Quickstart: Configure an application to expose a web API
Firstly, the scope is incorrect.
You should Expose an API in your API App Registration and then add it as a permission in your UI App Registration. You can refer to this document.
And when you try to call the 'https://login.windows.net/{tenant}/oauth2/authorize endpoint, you need to specify the scope to include api://{app id of the API App Registration}. For example: api://{app id of the API App Registration} openid profile email. Then the access token would be for calling your API.
At last, for CORS issue, please configure the CORS as * in your web app to see if it helps.
Try to follow this step: Configure App Service to return a usable access token
In my experience, this problem occurs, when you try to authorize against version 1 of the endpoint.
Instead of calling
https://login.microsoftonline.com/{tenant}/oauth2/authorize
call
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize
You might be required to set something like "metadata URL" in you authorization library to:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/.well-known/openid-configuration
Make sure your builder follows this order...lifted from our API program.cs
These must be in order of
UseRouting -> UseAuthentication -> UseAuthorisation -> MapControllers
> app.UseRouting()
> app.UseAuthentication()
> app.UseAuthorization()
> app.MapControllers()
If app.UseAuthentication and app.UseAuthorization are not in this order in statement position you Will get 401 Unauthorised as at 01/2023 .Net 6 Core.

How to get user info with a valid Bearer Token?

At work we are making an SPFx Web Part React client app that deploys to SharePoint as a Web Part. Our back-end is a ASP.NET Core 2.2 Web API that is secured using Azure Portal's built in Authentication feature. The front-end is using AadHttpClient that magically handles the authentication by taking the context of the current page (SharePoint) that has the user already logged in. Doing so, silent authentication occurs and the API call is successfully made with authentication successfully passed. The AadHttpClient is supposed to magically bundle up the token in the request header that gets sent to the back-end Web API. I still need to debug the live development app and see how to retrieve the Bearer Token in the back-end Web API. These are my next probable steps?
Would I just probably use 'string bearerToken = Request.Headers.....;' or 'string bearerToken = Request.Headers["KeyValue"]' to get the token itself?
Assuming I can get this Bearer Token, how can I check the caller's user information? Is it just var userName = User.Identity.Name;? Or would I or could I use the token and some how make a call to Microsoft Graph API to view the user's info?
If you are using ASP.NET Core and using default authentication then things are bit easier. From documentation you can see that several tokens are injected in the request header based on Identity provider so in your case you have to look for following headers which Azure AD injects. These headers would contain ID Token which you would need to verify the claims and get user information.
X-MS-TOKEN-AAD-ID-TOKEN
X-MS-TOKEN-AAD-ACCESS-TOKEN
X-MS-TOKEN-AAD-EXPIRES-ON
X-MS-TOKEN-AAD-REFRESH-TOKEN
Ideally all the claims are injected automatically in ClaimsPrincipal
you can find more here
Official Docs
How To extract Token

Google OAuth2 flow and id_token refresh

I am having troubles in implementing OAuth in the right way.
I use a client/API architecture (Angular for front and Node.js for back) and I would like user to sign in using Google OAuth authentication only.
Here is what I think is the right way for the moment (tell me if I misunderstood something) :
Angular open a Google popup asking user's consent.
Once the user agree, Google Authorization server sends back to angular a verification code.
This verification code is forwarded to an API endpoint.
Then, the API asks Google Authorization server to exchange this code for an access_token, an id_token and a refresh_token.
Google sends those 3 tokens.
The API uses access_token to retrieve user from Google API
The API persists the user
Here is the little dillema, in my opinion, the access_token and refresh_token should be stored into the database and the id_token should be sent back to Angular client.
This way, it would allow the API to ask for resource in Google API and if the token expires it can still ask for a new token thanks to the refresh_token.
Client-side, the id_token is embedded in all requests thus allowing the API to identify the client and verify his authentication with Google certs from https://www.googleapis.com/oauth2/v3/certs.
Supposing this is right way to use tokens, how could I deal with id_token expiration since client does not have any refresh token ?
Thanks !
I do it slightly different (I have the same basic architecture though).
Angular decides the user needs to log in and displays a login popup.
The url in the login popup is not serviced by angular, but is instead directly run off of the backend server: /auth/google . (I use hapijs and bell, personally).
/auth/google is serviced by a bell plugin and initiates the OAUTH dance.
the end of the OAUTH dance results in my node server generating a local token (I just generate random bytes and store them in redis mapped to user ids)
because the initial login popup was created by window.open, the success page (generated on the api side rather than in angular) can use window.opener.postMessage to communicate the token back to the angular runtime.
This way, all my sensitive google credentials (the user's oauth token, refresh token if needed, and my application's api ID and secret) are only on the server, except for during the OAUTH dance relay when they're in a URL string during the client redirects. This is reasonably secure.
Then for all the actual user interactions with the api, I use the token I generated in step four to authenticate. This could be a JWT if you wanted, but I don't do it that way; I just use redis to map from 'longrandostring' -> userId. That lets me (for example) force everyone to re-login if I wipe the redis database that has all the tokens stored, or I can write a lua script to delete all the entries that map to a certain userid.
If you need a refresh token, you can set access_type=offline in the initial request to oauth2/auth, and you'll get a refresh token as part of the response, unless you've previously gotten a refresh token. You can then persist it on the server side and get new access tokens as needed. If you set approval_prompt=force as well, you'll force a new consent screen and be guaranteed a refresh token (but after some small number of refresh tokens granted to a user, older ones expire on the same application so it's best to only request them if really needed).

Siteminder SSO + Spring Security + Angular JS

I have seen lot of examples where, there is a custom Login page with Angular JS, and then we make a rest POST call with the username/pwd, and then Spring authenticates based on whatever Auth Service we provide. Then we receive a success, grab the user object from Spring Security and then create a Session cookie in Angular.
https://github.com/witoldsz/angular-http-auth/blob/master/src/http-auth-interceptor.js
I also have seen, integrating Siteminder with Spring Security where we install a policy agent on the web server, and then grab request headers with Spring Security, and then pull the roles and build a user profile object.
I'm looking for a solution where I can combine both the above. This is the scenario :
When the user requests for index.html (Angular), the policy agent on the web server intercepts, authenticates with a Siteminder login page and then passes the headers to the app server. The Spring Security on app server will read the headers and pull the roles from our app database and then build a userprofile object. Now here, I want to continue the flow and display angular page, but Im trying to figure out, how do I send the user profile object to angular, because angular is not making a POST call at this point. Also, how do I get the http-auth-interceptor in play, because I need to keep checking if the user is still authenticated on the change of every view/state in Angular.
Help appreciated ! Thanks !
You may implement a tiny JSON REST service "/your-app/profile" which is protected by SiteMinder, reads and evaluates the headers and returns the result as a JSON object.
Your Angular App (e.g. /your-app/index.html) should better also be protected by SiteMinder so you receive an immediate redirect to the SSO Login when accessing it without session. In addition, it must read the JSON REST resource "/your-app/profile" when loaded. It must also expect that SMSESSION is missing when reading "/your-app/profile" and react accordingly - perform a reload of the protected index.html page to trigger a SM SSO re-login (if "/your-app/index.html" is protected, otherwise you must trigger login by a redirect to some protected resource).
If you want to constantly check to see if SiteMinder session is still present, you may either access the "/your-app/profile" or check for the presence of the SMSESSION cookie (only in case it is not set as HTTP-only).
One SECURITY NOTE: If you rely on the seamless SSO which is provided via SMSESSION cookie, be aware of the possible CSRF (Cross-Site Request Forgery) attacks!
Apparently both roles and the username will be available in spring if the integration is done as this describes
Integrating Spring Security with SiteMinder

Angular token and user login scenario

I m building app who uses oauth2.
I me using:
Laravel for backend
Oauth2 for Laravel (lucadegasperi)
Angular for frontend because it will be also and native mobile app:D.
My question is?
What is the workflow for user sign in?
Now i have.
User comes to site and enter username and password
Angular send post for access token and when access token is returned i go for user data. Then I store access_token in localstorage. I m using grant_type=password i forget to mention.
I have 2 hours when token gona expire. In that moment when token expire I go for new token by refresh_token functionality.
My Questions are:
Is this good way/approach?
What is supposed to happen when user close browser?
Now when user close browser and again enter to my app. I will check localstorage and then autheticate user by access_token. If Access Token is expired i will get new one.
What about remeber me option or so called keep me signed in?
Does it mean thant i must set token that will be expired in 365 days (lifetime)?
or create cookie/ localstorage with access token so when user comes newt time i read cookie/loaclastorage and then authorize user?
And finnaly about destroying token. Now my token will be detroyed when i log of from the app.
Thanks
We are building the same kind of service/app using the same components. We use a password flow and I store the token in local storage if the user ticks the "remember me" checkbox on the login form, otherwise I just store the token in an un-persisted variable that gets destroyed when the user refreshes or closes the browser.
See some notes on testing protected endpoints here:Testing OAuth 2.0 protected API endpoints in Laravel
Marijan!
I'm working on simple app containing two separate layers. 1) Rails 5 Json API provider. 2) Separate NodeJS server running Angular 2 application.
Angular 2 app on Login requests access token from google
Angular 2 app retrieves UserInfo from google/people API
Angular 2 app now able to POST json with User's display name and some id from Google Response json.
Angular 2 POSTs json to my Rails 5 API server (partially implemented, but already works with login/pass auth).
So far I have implemented implicit OAuth2 using the code similar to this Gist. Using this code I am able to get User Identification Info which is enough for me to identify the user in API provider or create account for it.
This approach works for me. Hope it will work for you as well.
Note: this approach might be insecure.

Resources