0

I would like to create a website and app where users can search a song and collect it into a public list (saved to a database). Therefore, I would not like to let the user authenticate himself just to add 1 song to the list. Because you need to provide a token in order to search, I've found several options:

  1. I will save the token into the database (refresh every hour using a CRON job), and when the user wants to search, I will retrieve the code and append it client side so the request will be successful. This, of course, exposes the token, even though it can only search, it is not really safe. PHP is no option, as it has to be a website and an app

  2. I need to let everyone log in which is very annoying

  3. I need to make a PHP script that will receive some endpoints from the client side and will execute it server side and send the response back. This, however, does not scale really well when there are a lot of users and the rate-limiting from one IP will soon be activated.

Are there any other options I can try?

EDIT: The songs should be searched by calling the Spotify API, not everyone has Spotify, therefore I was thinking about one token that could be shared

Jason
  • 1,658
  • 3
  • 20
  • 51
  • 2
    Failing to understand a special case here. Why do existing token based authentication schemes not work? – ficuscr Oct 18 '18 at 19:43
  • You could always look at implementing a [Token based authentication](https://stackoverflow.com/questions/29121112/how-to-implement-token-based-authentication-securely-for-accessing-the-website) question already answered if you're still unsure. – Jaquarh Oct 18 '18 at 20:07
  • Not everyone has a Spotify account, so therefore I cannot require everyone to log in – Jason Oct 20 '18 at 08:05

2 Answers2

1

If you're looking to use OAuth as a means of TLS between the server and client then each user must authenticate against the server with a request of information.

Since, I assume, this is not a public API (for anyone to access data), you only want your client app to be able to authorise such requests.

In this case, you would not need to send a 'scope' to the authentication server, simply just generate a resource token but FORCE the user to login.

Using that resource token, the client will send a second request to the resource server. Inside this request should hold the ACTION and DATA for that request and on receipt should then delete that token from the database. There is no need for a CRON job.

Client -> Authentication Server
       <- Resource Token (OK)
       <- Status BAD

Client -> Resource Server { Resource Token, Action, Data }
       <- Status OK
       <- Status BAD
  • Check the token exists and "in-date"
  • Check that the action is permitted
  • Check that the data is more than 1 song
  • Execute the insert, remove the token and return a response header

The reason you do not need a CRON job is because you should set a timeout for the token. For example, add a (TIMESTAMP) created DEFAULT CURRENT_TIMESTAMP to the database, pull the row out of the database for that token and ensure that it wasn't created n minutes ago, if it was then its void (expired) and can no longer be used.

Here is a URI example for the resource server:

/api/resource_token/action?data=

Of course, data should be a POST parameter but, for this, it was easier to show it as a GET request. It doesn't need to hold ALL the data, it could be anything like:

?song=[{"artist": "foo", "song": "bar"}]&type="json"

Using AltoRouter it would look something like this:

$router->map('GET|POST', '/api/[*:token]/[*:action]', function($resourceToken, $requestAction) {

    foreach(array('Song', 'Type', 'PlaylistId') as $param)
        if(!isset($_POST[$param]))
            die(...Return your response header error...);

    if(($token = SomeModel::getToken($resourceToken))->isValid())
        SomeController->using($token)->execute($requestAction);

    die(...Return your response header success...);

}, 'API');
Jaquarh
  • 6,493
  • 7
  • 34
  • 86
  • I've edited my question, I am using Spotify's API for the song search, and not everyone has Spotify so therefore logging everybody in is not an option – Jason Oct 20 '18 at 08:06
1

Less annoying but not secure:

Mobile App

First time the app is used:

  1. Require authentication and capture the device UUID.
  2. Store the device UUID in the database which is related to the authenticated user and also related to the user's play list.

Next time the app is used the device UUID already exists in the database so assume the related play list is the one to use.

Browser

First time the page (or after clearing cookies) is used:

  1. Require authentication and set a long-lived cookie.
  2. Store the cookie in the database which is related to the authenticated user and also related to the user's play list.

Next time the page is used the cookie will already exist so assume the related play list is the one to use.

Andrew S
  • 2,509
  • 1
  • 12
  • 14