{"id":418,"date":"2021-10-18T07:43:13","date_gmt":"2021-10-18T07:43:13","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/spring-boot\/?p=418"},"modified":"2021-10-20T04:15:48","modified_gmt":"2021-10-20T04:15:48","slug":"complete-application-with-spring-boot-role-based-authorization","status":"publish","type":"post","link":"https:\/\/kindsonthegenius.com\/spring-boot\/complete-application-with-spring-boot-role-based-authorization\/","title":{"rendered":"Complete Application with Spring Boot \u2013 Part 7 (Role-Based Authorization &#8211; 1)"},"content":{"rendered":"<p>In this lesson we would setup the role based authorization and be able to restrict resources based on users role.<\/p>\n<p>We would cover the following in this tutorial:<\/p>\n<ol>\n<li><a href=\"t1\">Setup the Security Packages<\/a><\/li>\n<li><a href=\"t2\">Create the Role Class<\/a><\/li>\n<li><a href=\"t3\">Modify the User Model to Include Roles<\/a><\/li>\n<li><a href=\"t4\">Create the Role Repository and Service<\/a><\/li>\n<li><a href=\"t5\">Write the AssignRole() and UnassignRole() Methods<\/a><\/li>\n<li><a href=\"t6\">Write the GetUserRoles() and GetUserNotRoles() Methods<\/a><\/li>\n<\/ol>\n<p>Watch the video tutorial here<a href=\"https:\/\/youtu.be\/lD7HRqCc3Hw\" target=\"_blank\" rel=\"noopener\">Watch the video tutorial here<\/a><\/p>\n<h5><strong>1. Setup the Security Packages<\/strong><\/h5>\n<p>We would need to place all the security-related files in the same package. So go ahead to create a package called security. Also four sub-packages as shown below:<\/p>\n<ul>\n<li>Security\n<ul>\n<li>controllers<\/li>\n<li>models<\/li>\n<li>repositories<\/li>\n<li>services<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h5><strong>2. Create the Role class<\/strong><\/h5>\n<p>Inside the models package, create a class called Role. This class would be as follows:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Entity<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@Data<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@NoArgsConstructor<\/span>\r\n<span style=\"color: #555555; font-weight: bold;\">@AllArgsConstructor<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Role<\/span> <span style=\"color: #008800; font-weight: bold;\">extends<\/span> Auditable<span style=\"color: #333333;\">&lt;<\/span>String<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #333333;\">{<\/span>\r\n    <span style=\"color: #555555; font-weight: bold;\">@GeneratedValue<\/span><span style=\"color: #333333;\">(<\/span>strategy <span style=\"color: #333333;\">=<\/span> GenerationType<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">IDENTITY<\/span><span style=\"color: #333333;\">)<\/span>\r\n    <span style=\"color: #555555; font-weight: bold;\">@Id<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> Integer id<span style=\"color: #333333;\">;<\/span>\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String description<span style=\"color: #333333;\">;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">private<\/span> String details<span style=\"color: #333333;\">;<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>I have used Auditable. <a href=\"https:\/\/www.kindsonthegenius.com\/auditing-in-spring-bootstep-by-step-tutorial\/\" target=\"_blank\" rel=\"noopener\">You can review how to use it here<\/a>. <a href=\"https:\/\/youtu.be\/Hg0Yvlv8Jb0\" target=\"_blank\" rel=\"noopener\">JPA Auditing video here<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h5><strong>3. Modify the User Model to include Roles<\/strong><\/h5>\n<p>You need to modify the User model to include a new filed, roles. This would be a Set of all the roles assigned to the user.<\/p>\n<p>So, open the User.java file and add the following:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@ManyToMany<\/span><span style=\"color: #333333;\">(<\/span>cascade <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">{<\/span>CascadeType<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">ALL<\/span><span style=\"color: #333333;\">},<\/span> fetch <span style=\"color: #333333;\">=<\/span> FetchType<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">EAGER<\/span><span style=\"color: #333333;\">)<\/span>\r\n        <span style=\"color: #555555; font-weight: bold;\">@JoinTable<\/span><span style=\"color: #333333;\">(<\/span>\r\n                name <span style=\"color: #333333;\">=<\/span> <span style=\"background-color: #fff0f0;\">\"user_role\"<\/span><span style=\"color: #333333;\">,<\/span>\r\n                joinColumns <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">{<\/span><span style=\"color: #555555; font-weight: bold;\">@JoinColumn<\/span><span style=\"color: #333333;\">(<\/span>name <span style=\"color: #333333;\">=<\/span> <span style=\"background-color: #fff0f0;\">\"user_id\"<\/span><span style=\"color: #333333;\">)},<\/span>\r\n                inverseJoinColumns <span style=\"color: #333333;\">=<\/span> <span style=\"color: #333333;\">{<\/span><span style=\"color: #555555; font-weight: bold;\">@JoinColumn<\/span><span style=\"color: #333333;\">(<\/span>name <span style=\"color: #333333;\">=<\/span> <span style=\"background-color: #fff0f0;\">\"role_id\"<\/span><span style=\"color: #333333;\">)}<\/span>\r\n        <span style=\"color: #333333;\">)<\/span>\r\nSet<span style=\"color: #333333;\">&lt;<\/span>Role<span style=\"color: #333333;\">&gt;<\/span> roles <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">new<\/span> HashSet<span style=\"color: #333333;\">&lt;&gt;();<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong>4. Create the Role Repository and Service<\/strong><\/h5>\n<p>We need create the RoleRepository interface in the repositories package. Then we also create the RoleService in the services package.<\/p>\n<p>Now, in the RoleService, take the following steps:<\/p>\n<p><strong>Step 1<\/strong> &#8211; Autowire the UserRepository and RoleRepository<\/p>\n<p><strong>Step 2<\/strong> &#8211; Write the findAll(), findById(), save() and delete() methods<\/p>\n<p>&nbsp;<\/p>\n<h5><strong>5. Write the Assign() and Unassign() Methods<\/strong><\/h5>\n<p>These two methods would be used to assign a role to a user or unassign a role to a user. You&#8217;ll write them in the service a well. You can find the two method below:<\/p>\n<p>For assignUserRole()<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/Assign Role to User<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">assignUserRole<\/span><span style=\"color: #333333;\">(<\/span>Integer userId<span style=\"color: #333333;\">,<\/span> Integer roleId<span style=\"color: #333333;\">){<\/span>\r\n    User user  <span style=\"color: #333333;\">=<\/span> userRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">findById<\/span><span style=\"color: #333333;\">(<\/span>userId<span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">orElse<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">null<\/span><span style=\"color: #333333;\">);<\/span>\r\n    Role role <span style=\"color: #333333;\">=<\/span> roleRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">findById<\/span><span style=\"color: #333333;\">(<\/span>roleId<span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">orElse<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">null<\/span><span style=\"color: #333333;\">);<\/span>\r\n   Set<span style=\"color: #333333;\">&lt;<\/span>Role<span style=\"color: #333333;\">&gt;<\/span> userRoles <span style=\"color: #333333;\">=<\/span> user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getRoles<\/span><span style=\"color: #333333;\">();<\/span>\r\n   userRoles<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">add<\/span><span style=\"color: #333333;\">(<\/span>role<span style=\"color: #333333;\">);<\/span>\r\n   user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">setRoles<\/span><span style=\"color: #333333;\">(<\/span>userRoles<span style=\"color: #333333;\">);<\/span>\r\n   userRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">save<\/span><span style=\"color: #333333;\">(<\/span>user<span style=\"color: #333333;\">);<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>For unassignUserRole()<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/Unassign Role to User<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">public<\/span> <span style=\"color: #333399; font-weight: bold;\">void<\/span> <span style=\"color: #0066bb; font-weight: bold;\">unassignUserRole<\/span><span style=\"color: #333333;\">(<\/span>Integer userId<span style=\"color: #333333;\">,<\/span> Integer roleId<span style=\"color: #333333;\">){<\/span>\r\n    User user  <span style=\"color: #333333;\">=<\/span> userRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">findById<\/span><span style=\"color: #333333;\">(<\/span>userId<span style=\"color: #333333;\">).<\/span><span style=\"color: #0000cc;\">orElse<\/span><span style=\"color: #333333;\">(<\/span><span style=\"color: #008800; font-weight: bold;\">null<\/span><span style=\"color: #333333;\">);<\/span>\r\n    user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getRoles<\/span><span style=\"color: #333333;\">().<\/span><span style=\"color: #0000cc;\">removeIf<\/span><span style=\"color: #333333;\">(<\/span>x <span style=\"color: #333333;\">-&gt;<\/span> x<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">()==<\/span>roleId<span style=\"color: #333333;\">);<\/span>\r\n    userRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">save<\/span><span style=\"color: #333333;\">(<\/span>user<span style=\"color: #333333;\">);<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h5><strong>6. GetUserRoles() and GetUserNotRoles()<\/strong><\/h5>\n<p>As you might have thought, these methods are used to return list of a particular user&#8217;s roles and list of roles not assigned to a user.<\/p>\n<p>GetUserRoles(user) is quite simple. Just return user.getRoles() as shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">public<\/span> Set<span style=\"color: #333333;\">&lt;<\/span>Role<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">getUserRoles<\/span><span style=\"color: #333333;\">(<\/span>User user<span style=\"color: #333333;\">){<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">return<\/span> user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getRoles<\/span><span style=\"color: #333333;\">();<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>GetUserNotRoles is not that simple. We actually need to use an SQL statement.\u00a0 So we have to extend the RoleRepository to include this:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #555555; font-weight: bold;\">@Query<\/span><span style=\"color: #333333;\">(<\/span>\r\n        value <span style=\"color: #333333;\">=<\/span> <span style=\"background-color: #fff0f0;\">\"SELECT * FROM role WHERE id NOT IN (SELECT role_id FROM user_role WHERE user_id = ?1)\"<\/span><span style=\"color: #333333;\">,<\/span> \r\n        nativeQuery <span style=\"color: #333333;\">=<\/span> <span style=\"color: #008800; font-weight: bold;\">true<\/span>\r\n<span style=\"color: #333333;\">)<\/span>\r\nList<span style=\"color: #333333;\">&lt;<\/span>Role<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">getUserNotRoles<\/span><span style=\"color: #333333;\">(<\/span>Integer userId<span style=\"color: #333333;\">);<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>You can then write the method in the UserService like shown below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">public<\/span> List<span style=\"color: #333333;\">&lt;<\/span>Role<span style=\"color: #333333;\">&gt;<\/span> <span style=\"color: #0066bb; font-weight: bold;\">getUserNotRoles<\/span><span style=\"color: #333333;\">(<\/span>User user<span style=\"color: #333333;\">){<\/span>\r\n   <span style=\"color: #008800; font-weight: bold;\">return<\/span> roleRepository<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getUserNotRoles<\/span><span style=\"color: #333333;\">(<\/span>user<span style=\"color: #333333;\">.<\/span><span style=\"color: #0000cc;\">getId<\/span><span style=\"color: #333333;\">());<\/span>\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>This completes Part 1 of Role Base Authorization. In part two, we would setup the controller methods and then create the HTML pages to manage the roles.<\/p>\n<p>Video Tutorial\u00a0<a href=\"https:\/\/youtu.be\/lD7HRqCc3Hw\" target=\"_blank\" rel=\"noopener\">Video Tutorial\u00a0<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>In this lesson we would setup the role based authorization and be able to restrict resources based on users role. We would cover the following &hellip; <!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":432,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2],"tags":[48,52,47,19],"class_list":["post-418","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring-boot-tutorials","tag-authorization","tag-granted-authority","tag-roles","tag-spring-security"],"_links":{"self":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/comments?post=418"}],"version-history":[{"count":5,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/418\/revisions"}],"predecessor-version":[{"id":436,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/posts\/418\/revisions\/436"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/media\/432"}],"wp:attachment":[{"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/media?parent=418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/categories?post=418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kindsonthegenius.com\/spring-boot\/wp-json\/wp\/v2\/tags?post=418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}