{"id":1835,"date":"2024-10-13T12:00:00","date_gmt":"2024-10-13T10:00:00","guid":{"rendered":"https:\/\/kindsonthegenius.com\/blog\/?p=1835"},"modified":"2026-08-28T10:16:11","modified_gmt":"2026-08-28T08:16:11","slug":"springboot-roles-and-privileges-3","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/blog\/springboot-roles-and-privileges-3\/","title":{"rendered":"InventoryMS \u2013 SpringBoot Roles and Privileges 3 (Implementing Granted Authorities)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Learn how to implement SpringBoot roles and privileges with Granted Authorities, design secure REST API routes, and restrict access using hasAuthority().<\/em><\/p>\n\n\n<h2>TL;DR<\/h2>\n<ul>\n<li>\n<p><strong>Granted Authorities<\/strong> represent the privileges or permissions a user has in Spring Security.<\/p>\n<\/li>\n<li>\n<p><strong><code>hasRole()<\/code> and <code>hasAuthority()<\/code><\/strong> are similar, but roles use the <code>ROLE_<\/code> prefix while authorities do not.<\/p>\n<\/li>\n<li>\n<p>A clear <strong>REST API route hierarchy<\/strong> makes it easier to apply authorization at a granular level.<\/p>\n<\/li>\n<li>\n<p><code>UserPrincipal<\/code> can return a user&#8217;s privileges as <strong><code>SimpleGrantedAuthority<\/code><\/strong> objects through <code>getAuthorities()<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong><code>hasAuthority()<\/code><\/strong> can then protect specific API endpoints based on privileges such as <code>VIEW_PRODUCT<\/code> and <code>CREATE_PRODUCT<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>This is Part 3 of our implementation of SpringBoot roles and Privileges for our Inventory Management System (InventoryMS). In this part we would discuss and implement granted authorities in Spring Boot.<\/p>\n<p>Parts 1 and 2 can be gotten from the links:<\/p>\n<ul>\n<li><a href=\"https:\/\/kindsonthegenius.com\/blog\/inventoryms-implementing-springboot-roles-and-privileges-1\/\" target=\"_blank\" rel=\"noopener\">SpringBoot Roles and Privileges \u2013 Standard Roles\/Privileges in an Inventory Management System<\/a><\/li>\n<li><a href=\"https:\/\/kindsonthegenius.com\/blog\/inventoryms-springboot-roles-and-privileges-2-the-data-model-and-api\/\" target=\"_blank\" rel=\"noopener\">SpringBoot Roles and Privileges \u2013 The Data Model and API<\/a><\/li>\n<li><a href=\"https:\/\/kindsonthegenius.com\/blog\/inventoryms-springboot-roles-and-privileges-3-implementing-granted-authorities\/\" target=\"_blank\" rel=\"noopener\">SpringBoot Roles and Privileges \u2013 Access Restriction Using Granted Authorities<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h4><strong>1. What are Granted Authorities?<\/strong><\/h4>\n<p>In Spring Security, we have the concept of Granted Authority. This represents a privilege or a permission granted to a user to perform a certain action.<\/p>\n<p><strong>What is difference between Role and Authority?<\/strong><\/p>\n<p>This two represent the same concept and are basically the same. The difference is how <a href=\"https:\/\/en.wikipedia.org\/wiki\/Spring_Boot\" target=\"_blank\" rel=\"noopener\">Spring Boot<\/a> handle the prefixing. A role is expected to be prefixed with \u201cROLE_\u201d but an authority is not.<\/p>\n<p>For example, the authority \u201cADMIN\u201d is the same as the role \u201cROLE_ADMIN\u201d.<\/p>\n<p><strong>hasRole() vs hasAuthority()<\/strong><\/p>\n<p>This is also the same in concept. When you use hasRole(\u201cADMIN\u201d), Spring Boot would expect that your role is named \u201cROLE_ADMIN\u201d. However, if you use hasAuthority(\u201cADMIN\u201d), Spring Boot would check if you have to role \u201cADMIN\u201d<\/p>\n<p>In our InventoryMS project, we would be using hasAuthority().<\/p>\n<p>&nbsp;<\/p>\n<h4><strong>2. Design the REST API Endpoint Pattern<\/strong><\/h4>\n<p>To be able to achieve and efficient way to protect your API, you will have to design the routing pattern. What does this mean? It means you need some hierarchy for the API route. For example:<\/p>\n<ul>\n<li><strong>top level:<\/strong> version number would (\/v1)<\/li>\n<li><strong>next level<\/strong>: modules for example, \/orders, \/products and \/suppliers<\/li>\n<li>from here you can have methods GET, POST, PUT and DELETE<\/li>\n<\/ul>\n<p>With this we would be able provide authorization at a granular level<\/p>\n<p>&nbsp;<\/p>\n<h4><strong>3. Retrieving the User\u2019s GrantedAuthorities<\/strong><\/h4>\n<p>To be able to protect our REST API based on user roles, we would have to do the following:<\/p>\n<p><strong>return the users authorities (privileges) from UserPrincipal<\/strong><\/p>\n<p>Here, we would need to update the getAuthorities method of the UserPrincipal class so that it returns a lit of SimpleGrantedAuthorities.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Override<\/span>\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> Collection<span style=\"color: #333333;\">&lt;?<\/span> <span style=\"color: #008800; font-weight: bold;\">extends<\/span> GrantedAuthority<span style=\"color: #333333;\">&gt;<\/span> getAuthorities<span style=\"color: #333333;\">()<\/span> <span style=\"color: #333333;\">{<\/span>\n    <span style=\"color: #008800; font-weight: bold;\">return<\/span> userPrivilegeAssignmentService<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getUserPrivileges<\/span><span style=\"color: #333333;\">(<\/span>user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">())<\/span>\n            <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">stream<\/span><span style=\"color: #333333;\">()<\/span>\n            <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">map<\/span><span style=\"color: #333333;\">(<\/span>privilege <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> SimpleGrantedAuthority<span style=\"color: #333333;\">(<\/span>privilege<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getDescription<\/span><span style=\"color: #333333;\">()))<\/span> <span style=\"color: #888888;\">\/\/ Use SimpleGrantedAuthority<\/span>\n            <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">collect<\/span><span style=\"color: #333333;\">(<\/span>Collectors<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">toList<\/span><span style=\"color: #333333;\">());<\/span>\n<span style=\"color: #333333;\">}<\/span>\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong>4. Configure Authorization Rules<\/strong><\/h4>\n<p>At this point we would have to configure the permission on the routes. So we would have to check if the user has the required authority before the request is permitted.<\/p>\n<p>The following changes would need to be made:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #333333;\">...<\/span>\n<span style=\"color: #333333;\">...<\/span>\n<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">authorizeHttpRequests<\/span><span style=\"color: #333333;\">(<\/span>auth <span style=\"color: #333333;\">-&gt;<\/span> auth\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"\/register\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">permitAll<\/span><span style=\"color: #333333;\">()<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"\/login\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">permitAll<\/span><span style=\"color: #333333;\">()<\/span>\n                \n                <span style=\"color: #888888;\">\/\/Configuration for the product module<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span>HttpMethod<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">GET<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"\/api\/v1\/products\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">hasAuthority<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"VIEW_PRODUCT\"<\/span><span style=\"color: #333333;\">)<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span>HttpMethod<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">POST<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"\/api\/v1\/products\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">hasAuthority<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"CREATE_PRODUCT\"<\/span><span style=\"color: #333333;\">)<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span>HttpMethod<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">DELETE<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"api\/vi\/product\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">hasAuthority<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"DELETE_PRODUCT\"<\/span><span style=\"color: #333333;\">)<\/span>\n                \n                <span style=\"color: #888888;\">\/\/Configuration for the order module<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span>HttpMethod<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">GET<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"\/api\/v1\/products\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">hasAuthority<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"VIEW_PRODUCT\"<\/span><span style=\"color: #333333;\">)<\/span>\n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">requestMatchers<\/span><span style=\"color: #333333;\">(<\/span>HttpMethod<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">POST<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"\/api\/v1\/products\"<\/span><span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">hasAuthority<\/span><span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"CREATE_PRODUCT\"<\/span><span style=\"color: #333333;\">)<\/span>                                \n                <span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">anyRequest<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">authenticated<\/span><span style=\"color: #333333;\">()<\/span>\n        <span style=\"color: #333333;\">)<\/span>\n<span style=\"color: #333333;\">...<\/span>\n<span style=\"color: #333333;\">...<\/span>\n<\/pre>\n<p>Then we would have to repeat this for all other roles we identified.<\/p>\n<p>You could also create an enum type to hold these roles instead of using just strings. But I see no added benefits for taking this extra step.<\/p>\n<p>Note that in our application, we use Roles only as grouping for privileges.<\/p>\n<h2>Frequently Asked Questions<\/h2>\n<p><strong>What is a Granted Authority in Spring Security?<\/strong><\/p>\n<p>A Granted Authority represents a permission or privilege that allows a user to perform a specific action within an application.<\/p>\n<p><strong>What is the difference between a role and an authority?<\/strong><\/p>\n<p>They represent similar concepts, but Spring Security handles their naming differently. Roles are typically prefixed with <code>ROLE_<\/code>, while authorities do not require that prefix.<\/p>\n<p><strong>What is the difference between <code>hasRole()<\/code> and <code>hasAuthority()<\/code>?<\/strong><\/p>\n<p><code>hasRole(\"ADMIN\")<\/code> checks for <code>ROLE_ADMIN<\/code>, while <code>hasAuthority(\"ADMIN\")<\/code> checks for the authority named <code>ADMIN<\/code>.<\/p>\n<p><strong>Why does InventoryMS use <code>hasAuthority()<\/code>?<\/strong><\/p>\n<p>InventoryMS uses privileges as the actual permissions for API access, with roles serving primarily as groups for those privileges. <code>hasAuthority()<\/code> therefore fits the application&#8217;s fine-grained authorization model.<\/p>\n<p><strong>How does <code>UserPrincipal<\/code> provide authorities?<\/strong><\/p>\n<p>The <code>getAuthorities()<\/code> method retrieves the user&#8217;s privileges and converts each one into a <code>SimpleGrantedAuthority<\/code>, which Spring Security can use when evaluating authorization rules.<\/p>\n<p><strong>Why is API route design important for authorization?<\/strong><\/p>\n<p>A consistent hierarchy such as version \u2192 module \u2192 HTTP method makes it easier to apply specific permissions to individual API operations.<\/p>\n<h2>Final Thoughts<\/h2>\n<p>Granted Authorities provide the connection between the privileges defined in InventoryMS and the actual security rules protecting its API. Once a user&#8217;s privileges are exposed through <code>UserPrincipal<\/code>, Spring Security can use those authorities to decide which operations the user is allowed to perform.<\/p>\n<p>Using <code>hasAuthority()<\/code> also supports the fine-grained approach established in the earlier parts of this series. Instead of treating roles as the final permission, InventoryMS uses roles to group privileges while individual authorities control access to specific API operations.<\/p>\n<p>With a consistent REST API structure and clearly defined privileges such as <code>VIEW_PRODUCT<\/code>, <code>CREATE_PRODUCT<\/code>, and <code>DELETE_PRODUCT<\/code>, you have a flexible foundation for controlling access across the application&#8217;s modules.<\/p>\n<p>&nbsp;<\/p>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to implement SpringBoot roles and privileges with Granted Authorities, design secure REST API routes, and restrict access using hasAuthority().<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pagelayer_contact_templates":[],"_pagelayer_content":"","footnotes":""},"categories":[414],"tags":[],"class_list":["post-1835","post","type-post","status-publish","format-standard","hentry","category-programming"],"acf":[],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1835","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/comments?post=1835"}],"version-history":[{"count":4,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1835\/revisions"}],"predecessor-version":[{"id":2530,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/posts\/1835\/revisions\/2530"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/media?parent=1835"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/categories?post=1835"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/blog\/wp-json\/wp\/v2\/tags?post=1835"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}