IdentityServer Offline Login Practices - authentication

I know this might be a very unusual question but I have been using IdentityServer 4 on .Net Core 2.1 for quite a while, serving all sorts of different APIs/Clients/Mobile Apps with connection to the internet at 'all times'.
Now I have encountered an interesting scenario where a User will have access to the internet and be able to authenticate with IdentityServer once but might not have access to internet after an X amount of time (X could be minutes/hours/days), but I still need to authenticate that user and login to use the 'offline features' of the app (even after closing the app).
I have thought about caching some credentials to then verify that the user is valid or using a system where I send an SMS code to then verify the user has the right phone (But that will only work if the app is on a mobile device, hence, not ideal). I'm still not set on any of the options.
I just wanted to ask if anyone else has encountered a similar problem like this, any suggestions would be appreciated. Please have in mind that the user may be logged out after using the app and still needs to be authenticated even if there is no internet connection. I like IdentityServer4 quite a lot, so I will prefer to keep it that way, and My App is developed using Xamarin Forms (iOS, Android, UWP), and the IdentityServer instance is on the cloud.
Thanks a lot for the help, any suggestion is appreciated.

Since only your service will know how to authenticate someone using their server-side credentials how about using the local secure platform features of the device (Secure Enclave, SafetyNet, whatever Windows does)?
The end result is that the user can use their already-configured PIN / fingerprint / faceprint to access your app, all backed by tamper-proof security hardware.
This also gives you the option to allow users to sign in only using their local credential by unlocking a previously stored refresh token. My banking app works like this for example - modern phones are really quite secure by default.
If you want to get fancy you could also enroll their device as a WebAuthn authenticator in your IdentityServer4 service and they could then use the same method to authenticate with the server when necessary.

Related

Smooth Authentication Flow on a Hololens 2 app

I'm trying to implement a smooth authentication flow for an hololens 2 app in a no-internet environment. Following setup is running currently
I'm hosting an identity server (Ory Kratos) with OAuth2 possibilities that holds user information.
I'm hosting a resource API that only logged in users should be able to access.
The user should be able to access their resources within the HL app. Possibilities to solve this are
Redirecting the user to a 2D page like in this article. But typing a long password in an Augmented Reality app is hard.
Using a second device (smartphone/laptop) like in this blog. But requiring another device is suboptimal.
Both approaches are fine, but they both lack a smooth user experience. My idea was to utilize the Windows Accounts that are already on the HL device. Microsoft Docs has a small section on how to take advantage of linked identities on HoloLens, see here. But it doesn't really explain how to "link" them to a custom identity server.
So I was wondering, is it possible to use these Windows Accounts that are already on the HL device and somehow link them to my identity server?
Or does anybody have a better idea to provide a smooth authentication flow in Augmented Reality? I'm open for ideas.
Windows Hello may meet your requirement. It works with the Azure Active Directory account or Microsoft Account connected in Windows settings, and it replaces passwords with strong 2FA by verifying your biometric. Besides, in Windows Hello architecture you no longer need to host your Ory Kratos OAuth2 server.

IdentityServer4 External Authentication without cookies

I'm having trouble understanding how ASP.NET Core authentication works.
I want to implement JWT access token authentication with refresh tokens. To my knowledge, this is the industry standard for authenticating a client (Mobile app, SPA Web application). For security purposes, I'd prefer to not implement my own authorization logic including JWT generation and refresh token handling. Since ASP.Net does not natively support this, Naturally my choice would be to use IdentityServer4, a large open source library for handling this kind of stuff.
However IdentityServer4 is heavily based on OAuth, and I'm not sure how that works with SPA applications and mobile apps (clients I trust). It requires the client to redirect to some arbitrary webpage to enter their credentials and then redirect back to the app. Gross. I've never seen a major app like Snapchat, Instagram, etc. have this kind of authentication flow where you are directed to some webpage/browser during the login flow. Luckily IdentityServer4 has a little feature to handle username/password authentication for my trusted clients (http://docs.identityserver.io/en/latest/quickstarts/2_resource_owner_passwords.html)
Great, that seems to suit my needs. But... Now I want to add Facebook Authentication. IdentityServer4 allows for External Authentication, however it is still cookie based (to my knowledge). Which requires the Android/iOS/SPA app to redirect to a webpage and then redirect back to the app. Again, this isn't ideal from a user perspective. Facebook provides native mobile SDKs to handle this type of authentication which returns an access token so there is no need to redirect to web pages using cookies.
Now lets say my iOS app uses the Facebook SDK to grab an access token for the user and sends it to the backend. The backend validates the token against the Facebook SDK, and subsequently registers a local user in it's own database.
Now when that same iOS user tries to login to the app, the app will generate a facebook access token for that user from the SDK and send it to the backend. However I'm not sure how to utilize IdentityServer4 to generate a JWT for the user since I need that users' username and password. This is where I'm stuck. I seem to be fighting against the library which makes me believe I am severely misunderstanding something.
TLDR; IdentityServer4 seems to be heavily based on cookies which doesn't really fit nicely into mobile apps/SPA webpages when you are redirected back and forth from authentication webpages. Am I using the wrong tool for the job? What are some alternative solutions?
As a note on big social apps: I think it comes down to who keeps the passwords. Facebook, Instagram, Snapchat, Google act as identity providers to third parties. They themselves require user to register and specify the password which they keep. Therefore they can use any customized approach for handling validation with those passwords. However, if any of them offerred a posibiltty to log-in with the other I.e Instagram were allowing to sign-in with Amazon credentials, then they would need to follow through a standard way like OAuth and redirect to the third party for log-in. Last time I checked Instagram, Facebook and Snapchat only offer to register and no option to sign in with 3rd parties which explains why the don't need redirects.
Now if we establish that a redirect is a necessary evil, then the means to carry over the data accross aren't that numerous. I.e. we either would need to pass data via a query string or use cookies. Am I missing any others?
Both have limitations but since cookies are persisted and browser carries them automatically with each request, they do seem like a better option for the job, especially if multiple redirects are required for an external IdP to track the state of authentication request. The same reason is mentioned here:
http://docs.identityserver.io/en/latest/topics/signin_external_providers.html
It's absolutely the right tool for the job if you want what OpenID Connect and OAuth2 give you. It sounds like you may need convincing though and it may be that your use case doesn't need the full breadth of functionality offered.
If you have multiple client applications and APIs in play then I think using OpenID Connect and IdentityServer4 the right choice at this point in time.
Regarding native apps, you used to word "gross" to describe using the user's default browser to perform the sign in process and it's understandable why you might think that at first but it's not as bad of a UX as you'd think and has plenty of advantages:
The client application is completely decoupled from how authentication is actually done be that federation, social sign in (Facebook in your case), multi-factor, retina scan etc. Your identity server deals with all that complexity and is a single point of management (and failure - so make it highly available!)
Single sign on is possible - if they're already signed into your IDP then they can go straight in (although you have full control of the flow - want them to consent or confirm the sign in request every time - you can do that)
If the user has a password manager set up in their browser then that'll work too
Both iOS and Android offer APIs for doing this stuff and the work well. If you skin your native and web UIs to look similar the flow from a user's PoV is not jarring at all.
You can still use refresh tokens (ultimately secured by the platform) so you don't actually have to do the interactive flow very often anyway.
Some additional reading below. Quite a lot of thinking has gone into this from the industry so it's definitely worth digesting the current best practice.
https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html
IETF current best practice: https://www.rfc-editor.org/rfc/rfc8252
Don't make Scott hate you ;) : https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications
For client side SPA browser apps OIDC provides the implicit grant type and uses a silent refresh and IDP session monitoring mechanism to maintain the session. Check out the oidc-client-js library which implements this approach.

Best practice for first-party auth in a native app

We have an auth infrastructure based on OAuth2 that is integrated into a variety of web apps within our organization. We also have a pure native application with no middle-ware of its own, and we want to integrate authentication into this native application. This application already has its own internal login mechanism with a native login screen, and we don't want to have it start launching external components like web browsers in order to display login windows. We are both the app provider and the auth provider, so the concern of the app having visibility into the user's credentials is less of an issue -- we trust ourselves to not intentionally do anything untoward with the user's credentials, and it's the same people writing a login form in the app as writing it on a web site. :-)
We are trying to figure out how best to support having the application continue to collect credentials the way it does now, but use them to obtain an auth token within our auth framework. With the APIs in place right now, the only way I can see for it to be done is to bake a Client Secret into the native app so that it can use a Resource Owner Password Credentials Grant request, since the code that would normally be making this call doesn't have a server side to live in. This feels really wrong, somehow. :-P
As far as I can see it, many of the structures of OAuth don't really apply to this app because it's not living in the context of a web browser, it doesn't have any concept of a "domain" nor any sort of "cross-domain" restrictions. It has been suggested that perhaps we create middleware for this app just for the purpose of exchanging authentication codes for tokens, but the rationale for that seems to be that this middleware theoretically ought to be able to somehow vet requests to determine whether they are legitimately from the application, and I don't see any way to do that that couldn't be faked by anyone with access to the client application code. Basically, the only purpose such middleware would serve would be to make the Client Secret irrelevant with respect to getting auth codes for credentials.
One thought that came to us was, how does something like Windows do it? Windows very obviously uses a native login form, but then some flow exists whereby the credentials that are entered are used for authentication and presumably, deep in the internals of the OS, for obtaining an auth token. Does anybody know if this architecture is documented anywhere? Does Microsoft's architectural choices here have any relation to OAuth2? What is the "best practice" for an application if you take it as a given that it doesn't have middleware and has its own native login form?
FWIW you don't need a client secret to use ROPC Grant to obtain or refresh tokens if the client is configured as a public client, i.e. a client that isn't capable of storing a secret.
RFC8252 OAuth 2.0 for Native Apps encourages using a native user agent for your scenario, using authorization code flows with PKCE. Authorization services like Okta and Auth0 have jumped onboard too, although they still recommend ROPC if the client is "absolutely trusted".
RFC6819 OAuth 2.0 Security discourages ROPC, but also says "Limit use of resource owner password credential grants to scenarios where the client application and the authorizing service are from the same organization", which are first-party apps.
So while the security verdict seems to be that authorization code+PKCE is the best practice, the UX hurdle of showing a user a browser window to log into a native app seem to be keeping ROPC alive. It's difficult to tell if that UX is jarring because people aren't used to it or because people can't get used to it.

API Authentication for multiple apps

I have been doing a lot of research into how to authenticate mobile apps with an API - I still feel a bit unsure about which flow & architecture would be better to use in my particular use case.
I think what's confusing me is some of the terminology used.
My use case:
An API & database on one server. Which holds the users & and the users resources.
A web app, which I have built and consumes the API. Hosted on the same server as the API. So it's dogfooding.
A web app, which I have built and consumes the API. Hosted on a different server to the API.
A mobile app, which I have built and consumes the API.
I'd like to be able to authenticate with the API using username & password.
The API will never be opened up for consumption by other 3rd party services except the web app and the mobile app.
Initially I felt like using the Resource Owner Password Credentials Grant flow would be sufficient. However in the docs it states that this flow should be used if "The client is absolutely trusted with the user credentials".
Since both my mobile & web apps will be built by me, I'm assuming they are seen as 1st party clients. Therefore am I right in thinking they are considered to be trusted with the user credentials? As I typically thought that when implementing oAuth, the idea would be to have the authentication server separate from the resource server. Which would allow you to have one authentication server for multiple APIs.
After reading this post: Why the Password Grant is not suitable for modern applications
It threw me off track a bit. But then, is this post talking about using this flow in my use case?
I was also looking at the Implicit Grant Tokens flow. However using this flow I couldn't really see how the user would enter their credentials first?
I also question if any of the oAuth flows is really needed for my use case and I should instead look at other ways of authenticating?
I'm really quite lost with this I would like some direction to go in with how to authenticate users in my particular case.
Thanks in advance!
I'll most likely be using Laravel to house my API and so I do have Passport available to me to implement oAuth
EDIT
From following this oauth article I've found that in all use cases of my app, I end at Password Credentials Grant flow. Would I be correct here?

OpenID authentication from an installed application

I'm currently planning a new web project. Clients are going to connect using a regular web browser and, in case of regular java-enabled cell phones, j2me client. I would really like to make use of the OpenID authentication. In case of regular web browser things are pretty straightforward. However, I am really not sure about installed applications (such as j2me client installed on a mobile device) - regular OpenID authentication is performed by entering username/password on a webpage of particular OpenID provider - which is quite a limitation :)
Has anyone coped with such a situation? Is it possible to create authentication mechanism to the site that uses OpenID from a mobile j2me client?
Currently, I think of solution that users who would like to connect from their mobiles download necessary j2me application from the server web site after they have authenticated themselves (regular browser authentication). The mobile client app could be assembled dynamically on the server with the SSL certificate embedded that is associated with particular logged in OpenID user. After that, j2me client could authenticate to the server without entering any username/password. The data that is going to be stored on the server is not THAT sensitive - considering cases of mobile phone thefts etc.
Can anybody come up with a better solution?
The best solution IMO for what you're doing is to use OAuth combined with OpenID. You're use of OpenID at the RP is fine. But for installed applications that need access to that web site, they should use OAuth to get authorized. The flow would work like this:
User installs app on their device
During install or on first launch, the app has an "Authorize me" button.
The user presses the button and a web browser pops up the web site that the client app needs to access data from.
User logs into that site using their OpenID
Site now asks "do you want to authorize client app X?"
User says yes and closes the browser.
The client app reappears and says "thanks." and now has the OAuth token necessary to access the user's data without the user ever logging in again.