REST API authentication for web app and mobile app
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.
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