All we need is an easy explanation of the problem, so here it is.
I’ve tried to find an answer to this question for a while now, but my efforts have been fruitless. I’ve found several articles and questions about offline authentication, but these are mainly concerned with storing login credentials locally after a user has already logged in once online.
The reason I want to implement such a system is because certain groups should have access to my applications for free, whereas others which do not fall under these groups should have to pay in order to use these applications. To my knowledge this is not something that is supported by the app store. Additionally eventually the series of applications should support other devices, so it makes sense to have a common login service.
These applications don’t need resources from a server. The server is used merely for authenticating the user.
When a user launches an app they must log in before they can use the app. The authentication takes place on a server and is already sorted. The question is how I can restrict use of the application, which is already installed on the device by the time the user is prompted log in. If this were a web application I would store a session cookie which is then used whenever a resource is requested. In my case all resources are already on the device, so if someone is stubborn enough they will be able to use the application without logging in first, but I don’t want this to be too easy. If there is some offline equivalent of a session cookie that I can use to verify that the user has logged in as the app is being used that would be ideal. I’m not storing any sensitive information in the applications nor would it be a catastrophe if someone were to gain access without first logging into an account, but I would like to know if there is a good way to solve this problem.
- When users launch my applications they should be prompted to login
- After logging in users should be able to use the application, and it shouldn’t be too easy circumvent the log-in process
I’m not asking for details, but I’ve hit a dead end and would like to know about any technologies or techniques that might help.
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
I think you have either over-complicated the issue in your head (common practice for us developers) or you have a design flaw in your system. Could be both.
Your question states:
How do I prevent users from using my iOS apps unless they have been authenticated on a server?
The answer to which is: don’t allow the app to start until a user has logged in. When you start the app, start it straight to a login screen. But, it appears you already have that in place:
When a user launches an app they must log in before they can use the app
So, really your question appears to be:
how I can restrict use of the application…?
Your user accounts need to have roles. At minimum, a free and premium user role.
Upon successful authentication, the user should obtain a token, which gives them use of the app. For the purposes of this discussion, I’ll say “unrestricted access to the app” to avoid the complexities of unlocking only this feature or that feature, which is completely possible depending on your architecture.
The token should not only give access to use the app, but also have an expiration option, but that’s up to you. (If a free user is perpetually free, and a premium user is a one-time-fee yields a perpetual license, then expirations are not necessary).
Once the user logs in for the first time, your user authentication server will issue a token based on their role and status. If they are a free user, they will receive this token, which gives them unfettered access to the app. If they are a premium user, then the server will withhold the token unless the premium has been paid.
Although the implementation method is a little out of scope for security.stackexchange.com, I’ll do a simplified version here because I think its part of the underpinnings of your original question.
The complication comes at this question: how do your premium users pay to unlock the app? You can’t have a free and a paid app because everyone would just download the free one and never pay.
You’re only left with the option of a single app and altering the user role based on a paid (or even subscription) status.
Since you’ve posted this in iOS, I’ll reference In-App purchases. The app should be free by default with in-app purchase options. When a free user downloads the app, they can request their free account (or, if they belong to a given group that has a coupon code, etc… they need the option of entering that, which will change their role on your server to a free user role).
Otherwise, you can leverage the in-app payments to upgrade the account to a premium / unlocked version.
This being said, having an app be “free” and then immediately require an unlock code or an in-app purchase will be a “high friction” implementation.
If you decided to go with a free and paid version in the app store. The free version would simply require a coupon code to activate the free subscription. Or, in the alternative, it would have to wait for your staff to approve the new user. (Lots of work for a free app).
The paid version would work right after the download. Here, you’re restricting the “high friction” implementation to users who are getting free stuff anyway. Paid users have a smooth as butter transaction.
The authentication takes place on a server and is already sorted
If your authentication server does not support roles, then this isn’t sorted, which may be a design flaw that needs to be revisited. Especially considering that if you don’t currently have user roles, you certainly would need to have code that either queries Apple’s API for subscription status, or have code that receives an event when a subsciption / fee has been paid to change a user’s role.
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂