Possible Solution:
You can make the scopes (scp in access token) be your permissions. Below are the steps:
- In your Authorization Server, create your custom scopes(permissions) and set them as default scopes (this is necessary).
For example create 2 default scopes:
books.read (default=true)
books.write (default=true)
Go to access policies in your Authorization Server create one if none is defined.
Create access policy rules in the access policies page, the rules will be your mapping between groups and scopes.
Test that in Token Preview tab, the trick here is to leave scopes field empty so that the Authorization server can return the default scopes that are set for the user, as explained by Okta:
A default scope will be returned in an access token when the client omits the scope parameter in a token request, provided this scope is allowed as part of the access policy rule.
Now in your application when requesting an authorization code make sure that scope query param is empty.
Depending on the library you are using you may face some issues if by default they are expecting an id_token to be always returned but you will probably be able to customize it. For example: https://github.com/okta/okta-auth-js/issues/827
Solution Limitations:
As mentioned in steps 4 and 5 we are omitting the scope query parameter, this mean that only our custom scopes assigned for the user or his groups will be returned, since the base scopes that are predefined by Okta such as profile, openid, email ... will not be returned. Which also means that we are skipping OIDC which needs the openid scope, so id_token will not be returned and only an access_token will. So this solution assumes that you don't need any of the base scopes predefined by Okta.
In case you need any of the base scopes
As described in the limitations, the solution assumes that you don't need any of the base scopes predefined by Okta. But in case you do then below is a solution that works in that case but not that nice.
When requesting an authorization code in the oauth flow, you need to send the request twice
first one: omit scope query param, so the default scopes are returned.
second one: append the returned scopes returned from the first request to the list of base scopes you wanted such as openid, profile, 'email`. So you would send something like (encoded already)
?scope=books.read%20books.write%20openid%20profile%20email
Disclaimer:
The above solution may not be recommended, but it works. If anyone can find any security issues with the above solution please leave it in the comments.