In AWS Cognito we could define a role/permissions as a custom attribute in the user pool, but we could have a User table and a caching database and fetch roles each time the user does a request.

Of course, the first approach avoids an unnecessary query, but is there a security problem in the second approach? Given that we have an authenticated user, is the application database secure enough to store the roles and permissions a user has in our system?

  • welcome - can you please edit your q to clarify, are you simply talking about eg. a user's rights to "do something" in the application itself, or, are you talking about storing some grant or authority (or even creds) in your app's db for another system?
    – brynk
    Commented Apr 16, 2023 at 10:50
  • only about the right to do something, like accessing some feature of the application or changing some data via the application. Commented Apr 16, 2023 at 15:48

1 Answer 1


This is very common and there are no requirements to vest this information with some 3rd party service. You can simply set the flags against the user record, but you expose yourself to the risk of privilege escalation if an adversary can find a way to modify those flags: either by changing the app db records, or by changing their session cookie (if your system encodes user priv's in this).

It's better if the control of this is "out of reach" of the web-facing application hosts. Something that can be done is to ensure the app db cred's can only read privilege information and not write, with some separate, more restricted process to administer. This would be considered a first line of defense.

You might then go a step further and "sign" these priv's at the time they're stored and "verify" on every use. Typically, you would use some symmetric crypto to do this, but you could also extend this to include an asymmetric component because it let's you quickly verify if signatures are valid, without needing the ability to produce a valid signature. For example:

uidprivs = uid + privs + time_set + ...
check = keyed_hash_digest( app_secret , uidprivs )
checksig = sign( secret_signing_key , check )
stored_privs = uidprivs + check + checksig

This would be stored against the user's db record and probably placed into the user's session after they authenticate successfully. (Note that if you stored this in session cookie, then you would go one step further and encrypt, ideally with aead, so the client can't scrutinise the contents.) Now when a user arrives on a webhost claiming they have certain privs:

privs_user, check_user, sig_user = read_stored_privs()
check = keyed_hash_digest( app_secret , privs_user )
valid = verify( public_signing_key , sig_user , check )
success = valid AND (check_user == check)

All of the protocols and solutions that do this are some variation on this theme. Usually some 3rd-party system would handle the signing aspect so that the signing key (secret) is placed out of reach of the web-facing application host. The web-hosts would hold the public portion of the signing key public_signing_key, as well as app_secret, so they can validate the claims made by users.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .