You are not worrying about the right things
Protecting information located on the client?
You don't need to do anything once the information has reached your client (ex.: your browser) in order to protect it. You could store the access token in a cookie, in a hidden field on your webpage, in html5 local cache or plainly visible directly in the middle of the page and it doesn't change anything (except shoulder surfing...).
Worrying about the access token once it's on the client is like opening notepad to write your email password and then worry that an attacker might be able to steal that information from a remote location. It doesn't happen. Unless your computer is already compromised but at this point you have already lost.
Where it makes sense to worry?
Usually, your information is vulnerable when it is in transit. In the case of OAuth2 (implicit flow), the access token will be in transit at two places :
- from the authorization server to your browser
- from your browser to the resource server
Protecting the information while it is in transit is as easy as using TLS everywhere. Which you should already be doing since you are using OAuth2 and it's required by the protocol.
Now the real problem
The way you intend to use OAuth2 is most likely not the way that you should be using it.
To understand why you will probably misuse OAuth2, you have to know about the flows. OAuth2 define 4 authorization flow
- Authorization Code (only good one but... keep reading)
- Implicit (false sense of security)
- Resource Owner Password Credentials (horrible idea)
- Client Credentials (not applicable to your case)
Since you using a javascript client, the only flow that works for you is the implicit flow and now starts the issues.
Implicit flow problems
There are many but let's just talk about the most critical one. Access token are not bound to a specific client! From the specification section 10.16 :
For public clients using implicit flows, this specification does not
provide any method for the client to determine what client an access
token was issued to.
This open the doors for attacker to impersonate you, the resource owner, and then gain access to the resource server. Let's keep reading section 10.16 :
A resource owner may willingly delegate access to a resource by
granting an access token to an attacker's malicious client. This may
be due to phishing or some other pretext. An attacker may also steal
a token via some other mechanism. An attacker may then attempt to
impersonate the resource owner by providing the access token to a
legitimate public client.
In the implicit flow (response_type=token), the attacker can easily
switch the token in the response from the authorization server,
replacing the real access token with the one previously issued to the
attacker.
Servers communicating with native applications that rely on being
passed an access token in the back channel to identify the user of the
client may be similarly compromised by an attacker creating a
compromised application that can inject arbitrary stolen access
tokens.
Any public client that makes the assumption that only the resource
owner can present it with a valid access token for the resource is
vulnerable to this type of attack.
That first attack is actually not even an attack but rather just a "flaw" in the implicit flow...
The next attack
Now starts the big troubles. You seem to be trying to use OAuth2 implicit flow as a form of delegated end-user authentication which it is not meant to provide. Back to the specification section 10.16
Authenticating resource owners to clients is out of scope for this
specification. Any specification that uses the authorization process
as a form of delegated end-user authentication to the client (e.g.,
third-party sign-in service) MUST NOT use the implicit flow without
additional security mechanisms that would enable the client to
determine if the access token was issued for its use (e.g.,
audience-restricting the access token).
At this point it's mostly game over for you.
How to mount that attack?
It's pretty simple. Let's say your REST service required an access token from facebook. All an attacker need to do is to host a service, for example stackoverflow, and require an access token from facebook. When you give the facebook access token to stackoverflow, stackoverflow (our attacker) can now impersonate you with your REST service.
All that because access tokens are not bound to a specific client.
A solution
Don't use the implicit flow and instead use the authorization code flow. Which means that your 100% client side app will need to no longer be a 100% client side app.
Why are you not using the server that is serving the angularjs client to your user to handle the OAuth2 flow?
Reference : https://www.rfc-editor.org/rfc/rfc6749