How to access UserInfo object in client app after authenticating with OpenId Connect provider - authentication

I'm very new to OAuth and OpenId Connect, I've been reading all I can about it but still not understanding it completely. I'm working with a client web app that has the ability to authenticate with OpenId Connect with just some simple configuration settings such as the identity provider url, client id, client secret, config endpoint etc. I set that up and I'm using an identity server that has been made available to use for this purpose. The problem I'm running into is that the client web app is mostly locked down, I don't have access to the source. I can only make some HTML and Javascript customizations via an admin interface, but I will need to get at some custom data that should be part of the profile JSON coming back from the UserInfo endpoint so I can take some action with it. Should I expect that the UserInfo profile JSON and/or the token needed to call the UserInfo endpoint be available in a browser cookie or somewhere that I can access it using Javascript? I've poked around using the F12 debugger and Fiddler but don't see what I need. Is this even possible without having access to the server-side code in the client web app?

Related

As a client how do I request an access token from the Identity Server using client ID & secret then use the token to gain access to the API?

Hello new to stack overflow and programming.
I have a simple ASP.NET Core web app and am using ngrok to host my app, and I want to be able to call to a company's identity server so that I have an access token to be able to access their API and create Webhooks to receive notifications for different events.
I already have a
clientID
Secret
URL (given by ngrok)
for the request body to receive the response.
How do I go about doing this?
You need to use Microsoft authentication libraries to achieve this.which is very easy to implement.
MSAL Library is just an implementation for enabling developers to acquire tokens from the Microsoft identity platform endpoint.
Since you already have ClientID, Secret and Redirect URL you can get a token as Acquire a token and call Microsoft Graph API.
However, I think what you really want is to integrate AAD. You can easily enable AAD authentication for your .NET web application. It uses OWIN middleware.

How to secure Web API with Auth0 without exposing ClientId & ClientSecret to client?

I am creating a new .Net Core Web API that is consumed by a new React client-side app. Both the client-side app and the Web API are on different hosts and protected by Auth0. I set up both the client-side app and the Web API in Auth0, and then I created a machine-to-machine app in Auth0 to be able to communicate with the Web API silently (without a user interface). The security flow works like this:
User tries to access client-side app.
User is re-directed to Auth0 to provide credentials.
Auth0 authenticates the credentials and returns user info (including user ID + access token) to client-side app.
Client-side app stores user info in local storage for future use until it expires.
Any calls to 3rd party APIs are routed through my own Web API, so 3rd party API keys are sitting in a safe place on the server, not on the client-side.
User accesses a page that requires a call to my Web API but we don't have an access token for my Web API yet.
Client-side app reads the ClientId & ClientSecret (hard-coded values) from .env file and makes a POST request to Auth0 to fetch an access token for my Web API (this is Auth0's recommended way of getting the access token for the Web API silently except they don't specify where the ClientId & ClientSecret would be stored).
Auth0 returns an access token for my Web API.
Client-side app stores the Web API access token in local storage for future use until it expires.
Client-side app invokes my Web API with newly acquired access token as the bearer token in the header.
Web API receives the access token, authenticates with Auth0 and fulfills the request.
All of the above is working for me but I am concerned about storing the Auth0 ClientSecret of my Web API in the client-side app. Although it is not visible on the screen or in a cookie anywhere, any capable user would be able to get at it by inspecting the network traffic.
Many people on the Internet seem to be fine with storing 3rd party API keys in .env files while others advise routing 3rd party API access through your own Web API ... and I am doing the latter. But I still need the Auth0 ClientSecret to get to my own Web API and I cannot figure out a better place way to get to it without storing them somewhere on the client-side.
One last-ditch solution I can think of is to not protect my Web API through Auth0 and instead every call from the client-side app to my Web API should include something unique (like the user ID from Auth0) that can be validated by the Web API. Thankfully, the user ID from Auth0 will be stored in our database when the user is set up initially, so this is actually possible.
Does Auth0 have any other way for me to get the Web API access token without providing the ClientSecret given that I already have the client-side app's access token? I am curious to know how others have secured both their client-side app and their Web API through Auth0.
You are correct, you should not include the client secret in your client-side app. Do not use a client credentials flow, instead use a auth code + PKCE or implicit flow.
With that being said, Auth0 should handle most of that if you are using a library or SDK.
You have two options for getting the token:
When requesting the initial access token and ID token add the Web API as an audience and request the related scopes.
Make a silent request using the checkSession function for Auth0.js or getTokenSilently for auth0-spa-js
Take a look at this:
https://auth0.com/docs/architecture-scenarios/spa-api/part-3

Implementing identity server behind web api owin authentication

I have two different client apps written in javascript connecting to two different web api. I am trying to implement identity server 3.
Is it possible to have identity server behind my web api owin
authentication api end point. In other words, is it possible to
route /token endpoint from owin in web api to call /authenticate
endpoint in identity server?
Is it possible to audit log to db in identity server including
failed request along with user's ip and browser agent. Also is it
possible to log user's ip even if i am calling from web api as my
web api is being called by a user using browser?
In my case should i keep two different user base for two different
projects or move all my users to identityserver. If i move all the
user info to identityserver, how am i going to handle all the joins
with other tables in different applications or should i keep a copy
of user with minimum info such as id, email and name?
It makes little sense to first call a web api and deal with authentication during that call.
Your client apps should first redirect the browser to IdentityServer where user would log in and be redirected back to your client app along with either access token (implicit flow) or authorization code (AuthorizationCode flow), depending on the client app having a back-end or not. Then, your client app would make requests to the webapi, passing the access token in the Authorization header.
As for different user bases, one approach might be to implement specific IUserService for each user base and either send a hint about which one to use in the acr_values or tie it to specific clients registered in IdentityService. Again, depending on the requirements.
Is it possible to have identity server behind my web api owin authentication api end point. In other words, is it possible to route /token endpoint from owin in web api to call /authenticate endpoint in identity server?
Yes and no - you cannot reroute those requests, but you can host identityserver in the same application as a web api. In Startup.cs, map a folder to identityserver.
It's not a good idea to do this, first of all, which api of the two will host idsrv? What if that api goes down and takes idsrv with, then the other api does not work anymore.
-> host idsrv separately, make both apis and both javascript apps clients in idsrv, login to idsrv from the javascript apps (=SSO) and use bearer tokens for the api
Is it possible to audit log to db in identity server including failed request along with user's ip and browser agent. Also is it possible to log user's ip even if i am calling from web api as my web api is being called by a user using browser?
Yes, this should be possible, check the logging implementation for idsrv, at the least you should be able to plug in a provider that writes to a database.
In my case should i keep two different user base for two different projects or move all my users to identityserver. If i move all the user info to identityserver, how am i going to handle all the joins with other tables in different applications or should i keep a copy of user with minimum info such as id, email and name?
Idsrv does not need to have all the user info, just an email-address is enough, you can use that as link to the user data in your api databases if you use that as unique identifier.

How to use oauth with 1st party client-side js app?

The model for our product is like this:
Api backend (headless)
I already have oauth set up and ready to use with a resource owner credentials grant. Anyone who wants to use our api can do so using either an API key or their username/password. Of course they also need their client ID and secret.
SPA frontend that accesses the Api
I have built an SPA that will uses the api to provide a portal GUI for our clients. Given that this client-side app is owned and administrated by us (so it's a trusted app) how can I safely authenticate users using only username/password with oauth?
Originally it was using a JWT auth system that only required username/pass but now that we've implemented oauth I'd like to consolidate. It's unreasonable to make every user need to also have their client id and secret on hand to login, but I want users to have full access to the api from the GUI.
I've looking at using CSRF tokens but how would that work with my app when nothing is generated server-side?
I'm not sure how to proceed.
EDIT: very similar to the problem here.
I have decided to use the solution described here.
And here is a snippet of my implementation
The TL;DR version is
Create a proxy between the app and the api
Store the client ID and secret in the proxy
App logs in using password grant type -- proxy intercepts login request and inserts client id and secret
On login response proxy returns access token as an encrypted cookie
Client stores cookie and sends with api requests (to proxy)
Proxy decrypts cookie and inserts access token into Authorization header before forwarding to api endpoint
For me this has several advantages over implementing something custom on the api itself:
No need for custom grant on oauth server
ID/secret is hidden from app securely and can still use password grant
oauth server can identify client (no need for separate client ids for each user)
You should not use the resource owner credential grant from a JavaScript application. The fact that you own and administer the application does not make it a trusted application.
A trusted client is an application that can keep a secret. SPAs or any JavaScript app cannot keep a secret.
You should use the implicit grant for non-trusted clients.

REST API authentication for web app and mobile app

I'm having some trouble deciding how to implement authentication for a RESTful API that will be secure for consumption by both a web app and a mobile app.
Firstly, I thought to investigate HTTP Basic Authentication over HTTPS as an option. It would work well for a mobile app, where the username and password could be stored in the OS keychain securely and couldn't be intercepted in transit since the request would be over HTTPS. It's also elegant for the API since it'll be completely stateless. The problem with this is for the web app. There won't be access to such a keychain for storing the username and password, so I would need to use a cookie or localStorage, but then I'm storing the user's private details in a readily accessible place.
After more research, I found a lot of talk about HMAC authentication. The problem I see with this approach is there needs to be a shared secret that only the client and server knows. How can I get this per-user secret to a particular user in the web app, unless I have an api/login endpoint which takes username/password and gives the secret back to store in a cookie? to use in future requests. This is introducing state to the API however.
To throw another spanner into the works, I'd like to be able to restrict the API to certain applications (or, to be able to block certain apps from using the API). I can't see how this would be possible with the web app being completely public.
I don't really want to implement OAuth. It's probably overkill for my needs.
I feel as though I might not be understanding HMAC fully, so I'd welcome an explanation and how I could implement it securely with a web app and a mobile app.
Update
I ended up using HTTP Basic Auth, however instead of providing the actual username and password every request, an endpoint was implemented to exchange the username and password for an access key which is then provided for every authenticated request. Eliminates the problem of storing the username and password in the browser, but of course you could still fish out the token if you had access to the machine and use it. In hindsight, I would probably have looked at OAuth further, but it's pretty complicated for beginners.
You should use OAuth2. Here is how:
1) Mobile App
The mobile app store client credentials as you state yourself. It then uses "Resource Owner Password Credentials Grant" (see https://www.rfc-editor.org/rfc/rfc6749#section-4.3) to send those credentials. In turn it gets a (bearer) token it can use in the following requests.
2) Web site
The website uses "Authorization Code Grant" (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1):
Website sees unauthorized request and redirects browser to HTML-enabled autorization endpoint in the REST api.
User authenticates with REST service
REST site redirects user back to website with access token in URL.
Website calls REST site and swaps access token to authorization token.
Here after the website uses the authorization token for accessing the REST service (on behalf of the end-user) - usually by including the token as a "bearer" token in the HTTP Authorization header.
It is not rocket science but it does take some time to understand completely.
3) Restricting API access for certain applications
In OAuth2 each client is issued a client ID and client secret (here "client" is your mobile app or website). The client must send these credentials when authorizing. Your REST service can use this to validate the calling client
I resolved this for my own API quite easily and securely without the need to expose any client credentials.
I also split the problem into 2 parts. API authentication - is this a valid request from a recognised entity (website or native app). API authorisation, is that entity allowed to use this particular endpoint and HTTP verb.
Authorisation is coded into the API using an access control list and user permissions and settings that are set up within the API code, configuration and database as required. A simple if statement in the API can test for authorisation and return the appropriate response (not authorised or the results of processing the API call).
Authentication is now just about checking to see if the call is genuine. To do this I issue self signed certificates to clients. A call to the API is made from their server whenever they want - typically when they generate their first page (or when they are performing their own app login checks). This call uses the certificates I have previously provided. If on my side I am happy the certificate is valid I can return a nonce and a time limited generated API key. This key is used in all subsequent calls to other API endpoints, in the bearer header for example, and it can be stored quite openly in an HTML form field or javascript variable or a variable within an app.
The nonce will prevent replay attacks and the API key can be stolen if someone wants - they will not be able to continue using after it expires or if the nonce changes before they make the next call.
Each API response will contain the next nonce of if the nonce doesn't match it will return an authentication error. In fact of the nonce doesn't match I kill the API key too. This will then force a genuine API user to reauthenticate using the certificates.
As long as the end user keeps those certificates safe and doesn't expose the method they use to make the initial authentication call (like making it an ajax request that can be replayed) then the API's are nice and secure.
One way of addressing the issue of user authentication to the API is by requesting an authentication token from the API when the user logs in. This token can then be used for subsequent requests. You've already touched on this approach - it's pretty sound.
With respect to restricting certain web apps. You'll want to have each web app identify itself with each request and have this authentication carried out inside your API implementation. Pretty straight forward.