diff --git a/backend/RumahSehat/build.gradle b/backend/RumahSehat/build.gradle
index 12931c6f2d447dd679ab53dcff8b3d59ab899c4d..f558d3ce99e41319e3abc6ec5716b5b38a934a63 100644
--- a/backend/RumahSehat/build.gradle
+++ b/backend/RumahSehat/build.gradle
@@ -15,6 +15,8 @@ repositories {
 dependencies {
 	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
 	implementation 'org.springframework.boot:spring-boot-starter-web'
+	implementation 'org.projectlombok:lombok:1.18.22'
+	implementation 'org.projectlombok:lombok:1.18.22'
 	developmentOnly 'org.springframework.boot:spring-boot-devtools'
 	testImplementation 'org.springframework.boot:spring-boot-starter-test'
 	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
@@ -24,7 +26,8 @@ dependencies {
 	annotationProcessor('org.projectlombok:lombok:1.18.24')
 	implementation 'com.fasterxml.jackson.core:jackson-databind'
 	implementation 'org.springframework.boot:spring-boot-starter-webflux'
-
+	implementation 'org.springframework.boot:spring-boot-starter-security'
+	implementation 'com.auth0:java-jwt:4.2.1'
 }
 
 tasks.named('test') {
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java
index 51192fdaccc241fbef4d107e3d1da23fe666957e..c9a49cb339152a85f9da78764137c79bb7af2f21 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/RumahSehatApplication.java
@@ -1,7 +1,14 @@
 package apap.tugasakhir.RumahSehat;
 
+import java.util.ArrayList;
+
+import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import apap.tugasakhir.RumahSehat.models.PasienModel;
+import apap.tugasakhir.RumahSehat.service.PasienRestService;
 
 @SpringBootApplication
 public class RumahSehatApplication {
@@ -10,4 +17,20 @@ public class RumahSehatApplication {
 		SpringApplication.run(RumahSehatApplication.class, args);
 	}
 
+	@Bean
+	CommandLineRunner run(PasienRestService pasienRestService) {
+		return args -> {
+			pasienRestService.addPasien(PasienModel.builder().email("zachra@gmail.com")
+			.isSso(false)
+			.listAppointment(new ArrayList<>())
+			.nama("zachra")
+			.password("zachra")
+			.role("Pasien")
+			.saldo(0)
+			.username("zachra")
+			.umur(20)
+			.build());
+		};
+	}
+
 }
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..857b232fd14878876af62ccec3e1bbcddf3d24b0
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/JwtConfig.java
@@ -0,0 +1,55 @@
+// package apap.tugasakhir.RumahSehat.config;
+
+// import java.util.Date;
+// import java.util.HashMap;
+// import java.util.Map;
+
+// import com.auth0.jwt.JWT;
+// import com.auth0.jwt.JWTVerifier;
+// import com.auth0.jwt.algorithms.Algorithm;
+// import com.auth0.jwt.interfaces.DecodedJWT;
+
+// import org.springframework.beans.factory.annotation.Autowired;
+// import org.springframework.beans.factory.annotation.Value;
+// import org.springframework.security.core.userdetails.UserDetails;
+// import org.springframework.stereotype.Component;
+
+// import apap.tugasakhir.RumahSehat.models.UserModel;
+// import apap.tugasakhir.RumahSehat.service.UserService;
+
+// @Component
+// public class JwtConfig {
+    
+//     @Autowired
+//     UserService userService;
+    
+//     public static final Long JWT_TOKEN_VALIDITY = 180000L;
+
+//     @Value("${jwt.secret}")
+// 	private String secret;
+
+//     public String generateToken(UserDetails userDetails){
+//         var now = new Date(System.currentTimeMillis());
+//         var expDate = new Date(now.getTime() + JWT_TOKEN_VALIDITY);
+
+//         String username = userDetails.getUsername();
+//         UserModel user = userService.getUserByUsername(username);
+        
+//         Map<String, Object> claims = new HashMap<>();
+//         claims.put("id", user.getUuid());
+//         claims.put("username", username);
+//         claims.put("email", user.getEmail());
+//         claims.put("role", user.getRole());
+
+//         return JWT.create()
+//             .withSubject(username) // with claim, this will be replaced
+//             .withExpiresAt(expDate)
+//             .withClaim("claims", claims)
+//             .sign(Algorithm.HMAC256(secret.getBytes()));
+//     }
+    
+//     public DecodedJWT verifyToken(String token){
+//         JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret.getBytes())).build();
+//         return verifier.verify(token);
+//     }
+// }
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcf2cf47891fdb61f94c8b51d20eda8f3c3fda55
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/config/WebSecurityConfig.java
@@ -0,0 +1,68 @@
+package apap.tugasakhir.RumahSehat.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+// import apap.tugasakhir.RumahSehat.config.JwtRequestFilter;
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig /*extends WebSecurityConfigurerAdapter*/{
+
+    // @Autowired
+	// private JwtRequestFilter jwtRequestFilter;
+    
+    @Autowired
+    private UserDetailsService userDetailsService;
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+        http.csrf().disable()
+        .authorizeRequests()
+        .antMatchers("/css/**").permitAll()
+        .antMatchers("/js/**").permitAll()
+        .antMatchers("/**").permitAll()
+        .antMatchers("/login-sso", "/validate-ticket", "/authenticate").permitAll()
+        .anyRequest().authenticated()
+        .and()
+        .formLogin()
+        .loginPage("/login").permitAll()
+        .and()
+        .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+        .logoutSuccessUrl("/login").permitAll();
+        return http.build();
+    }
+    
+    // @Bean
+    // @Override
+    // public AuthenticationManager authenticationManagerBean() throws Exception{
+    //     return super.authenticationManagerBean();
+    // }
+
+    public BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+
+    @Autowired
+    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+        auth.inMemoryAuthentication()
+            .passwordEncoder(encoder)
+            .withUser("Frans")
+            .password(encoder.encode("apap"))
+            .roles("Admin");
+    }
+
+    @Autowired
+    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
+        auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
+    }
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java
new file mode 100644
index 0000000000000000000000000000000000000000..9310a7e032078a6caf86bc9e4adae692a1081505
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/PageController.java
@@ -0,0 +1,111 @@
+package apap.tugasakhir.RumahSehat.controller;
+
+import java.security.Principal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.beans.factory.annotation.Autowired;  
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.servlet.ModelAndView;
+
+import apap.tugasakhir.RumahSehat.models.AdminModel;
+import apap.tugasakhir.RumahSehat.models.UserModel;
+import apap.tugasakhir.RumahSehat.security.xml.Attributes;
+import apap.tugasakhir.RumahSehat.security.xml.ServiceResponse;
+import apap.tugasakhir.RumahSehat.service.AdminService;
+import apap.tugasakhir.RumahSehat.service.UserService;
+import apap.tugasakhir.RumahSehat.setting.Setting;
+
+@Controller
+public class PageController {
+    @Autowired
+    UserService userService;
+    @Autowired
+    AdminService adminService;
+
+    private WebClient webClient = WebClient.builder().build();
+
+    @RequestMapping("/")
+    private String home(Principal principal, Model model) {
+        if (principal == null){
+            model.addAttribute("status", "annonymous");
+        } else {
+            UserModel userModel = userService.getUserByUsername(principal.getName());
+            String role = userModel.getRole();
+            model.addAttribute("status", "loggedin");
+            model.addAttribute("user", userModel);
+            model.addAttribute("role", role);
+        }
+        return "home";
+    }
+
+    @RequestMapping("/login")
+    private String login() {
+        return "login";
+    }
+
+    @GetMapping("/validate-ticket")
+    public ModelAndView adminLoginSSO(
+        @RequestParam(value = "ticket", required = false) String ticket,
+        HttpServletRequest request
+    ) {
+        ServiceResponse serviceResponse = this.webClient.get().uri(
+        String.format(
+            Setting.SERVER_VALIDATE_TICKET,
+            ticket,
+            Setting.CLIENT_LOGIN
+        )
+        ).retrieve().bodyToMono(ServiceResponse.class).block();
+
+        Attributes attributes = serviceResponse.getAuthenticationSuccess().getAttributes();
+        String username = serviceResponse.getAuthenticationSuccess().getUser();
+
+        UserModel user = userService.getUserByUsername(username);
+
+        if (user == null) {
+            user = new AdminModel();
+            user.setEmail(username + "@ui.ac.id");
+            user.setNama(attributes.getNama());
+            user.setPassword("rumahsehat");
+            user.setUsername(username);
+            user.setIsSso(true);
+            user.setRole("Admin");
+            adminService.addUser((AdminModel) user);
+        }
+
+        Authentication authentication = new UsernamePasswordAuthenticationToken(username, "rumahsehat");
+        
+        SecurityContext securityContext = SecurityContextHolder.getContext();
+        securityContext.setAuthentication(authentication);
+
+        HttpSession httpSession = request.getSession(true);
+        httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
+
+        return new ModelAndView("redirect:/");
+    }
+    @GetMapping(value = "/login-sso")
+    public ModelAndView loginSSO(Principal principal){
+        return new ModelAndView("redirect:" + Setting.SERVER_LOGIN + Setting.CLIENT_LOGIN);
+    }
+
+    @GetMapping(value = "/logout-sso")
+    public ModelAndView logoutSSO(Principal principal){
+        UserModel user = userService.getUserByUsername(principal.getName());
+        if (user.getIsSso() == false){
+            return new ModelAndView("redirect:/logout");
+        }
+        return new ModelAndView("redirect:" + Setting.SERVER_LOGOUT + Setting.CLIENT_LOGOUT);
+    }
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6714213d1ee8b89ca6a01bc77baccc48e295192
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/controller/UserController.java
@@ -0,0 +1,74 @@
+package apap.tugasakhir.RumahSehat.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import apap.tugasakhir.RumahSehat.models.UserModel;
+import apap.tugasakhir.RumahSehat.service.UserService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+@Controller
+@RequestMapping("/user")
+public class UserController {
+    @Autowired
+    private UserService userService;
+
+    @GetMapping(value="/add")
+    private String addUserFormPage(Model model) {
+        List<String> listRole = new ArrayList<>();
+        listRole.add("Dokter");
+        listRole.add("Apoteker");
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        User users = (User) auth.getPrincipal();
+        String username = users.getUsername();
+        UserModel userModel = userService.getUserByUsername(username);
+        if (userModel.getRole().equals("Admin")){
+            UserModel user = new UserModel();
+            model.addAttribute("user", user);
+            model.addAttribute("listRole", listRole);
+            return "form-add-user";
+        } else {
+            return "invalid-role";
+        }
+    }
+
+    @PostMapping(value="/add")
+    private String addUserSubmit(@ModelAttribute UserModel user, Model model) {
+        user.setIsSso(false);
+        userService.addUser(user);
+        model.addAttribute("user", user);
+        return "redirect:/";
+    }
+    
+    @GetMapping(value = "/viewall")
+    public String viewAllUser(Model model){
+        List<UserModel> listUser = userService.findAll();
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        User user = (User) auth.getPrincipal();
+        String username = user.getUsername();
+        UserModel userModel = userService.getUserByUsername(username);
+        model.addAttribute("user", userModel);
+        model.addAttribute("listUser", listUser);
+        if (userModel.getRole().equals("Admin")){
+            return "viewall-user";
+        } else {
+            return "invalid-role";
+        }
+    }
+
+    
+
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed9957ab6dc0ea5df6e7bc6d5c3e49213f11bf38
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/filter/JwtRequestFilter.java
@@ -0,0 +1,74 @@
+// package apap.tugasakhir.RumahSehat.filter;
+
+// import java.io.IOException;
+// import java.util.ArrayList;
+// import java.util.List;
+
+// import javax.servlet.FilterChain;
+// import javax.servlet.ServletException;
+// import javax.servlet.http.HttpServletRequest;
+// import javax.servlet.http.HttpServletResponse;
+
+// import org.springframework.beans.factory.annotation.Autowired;
+// import org.springframework.http.HttpStatus;
+// import org.springframework.stereotype.Component;
+// import org.springframework.web.filter.OncePerRequestFilter;
+
+// import apap.tugasakhir.RumahSehat.config.JwtConfig;
+// import lombok.RequiredArgsConstructor;
+// import static org.springframework.http.HttpHeaders.AUTHORIZATION;
+
+
+// @Component
+// @RequiredArgsConstructor
+// public class JwtRequestFilter extends OncePerRequestFilter{
+    
+//     @Autowired
+//     private JwtConfig jwtConfig;
+
+//     @Override
+//     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+//             throws ServletException, IOException {
+
+//         if (isPathAllowed(request.getServletPath())){
+//             filterChain.doFilter(request,response);
+//         }else{
+//             String authorizationHeader = request.getHeader(AUTHORIZATION);
+//             if(authorizationHeader!=null && authorizationHeader.startsWith("Bearer ")){
+//                 try {
+//                     var token = authorizationHeader.substring("Bearer ".length());
+//                     jwtConfig.verifyToken(token);
+//                     filterChain.doFilter(request,response);
+//                 }catch(Exception e){
+//                     var authenticationException = new BaseResponse<>(false, HttpStatus.UNAUTHORIZED.value(), MESSAGE, null);
+//                     response.setStatus(HttpStatus.FORBIDDEN.value());
+//                     response.getWriter().write(convertObjectToJson(authenticationException));
+//                 }
+//             }
+//             else {
+//                 var authenticationException = new BaseResponse<>(false, HttpStatus.UNAUTHORIZED.value(), MESSAGE, null);
+//                 response.setStatus(HttpStatus.FORBIDDEN.value());
+//                 response.getWriter().write(convertObjectToJson(authenticationException));
+//             }
+//         }
+
+//     }
+
+//     private boolean isPathAllowed(String path) {
+//         var allowed = false;
+//         List<String> whiteList = new ArrayList<>();
+//         whiteList.add("/api/auth/login");
+//         whiteList.add("/api/auth/register");
+//         whiteList.add("/v3/api-docs");
+//         whiteList.add("/swagger-ui");
+//         for (String allowedPath: whiteList) {
+//             if (path.startsWith(allowedPath)) {
+//                 allowed = true;
+//                 break;
+//             }
+//         }
+//         return allowed;
+//     }
+
+    
+// }
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java
index 8382f7699cea0a05adef2f6b98e1cc02dff06ca5..71d7e0817ce281ad11673581af451b2d64c5b06d 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/AppointmentModel.java
@@ -2,6 +2,7 @@ package apap.tugasakhir.RumahSehat.models;
 
 import java.io.Serializable;
 import java.time.LocalDateTime;
+import java.util.List;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -12,6 +13,7 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -20,6 +22,8 @@ import org.hibernate.annotations.GenericGenerator;
 import org.hibernate.annotations.OnDelete;
 import org.hibernate.annotations.OnDeleteAction;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -60,5 +64,10 @@ public class AppointmentModel implements Serializable{
     @OneToOne(cascade = CascadeType.ALL)
     @JoinColumn(name = "kode_tagihan", referencedColumnName = "kode")
     private TagihanModel tagihan;
+    
+    // @JsonIgnore
+    @OneToOne(cascade = CascadeType.ALL)
+    @JoinColumn(name = "resep_id", referencedColumnName = "id")
+    private ResepModel resep;
 
 }
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java
index 02f7889ddda2301e83f36b08409cd23f458837e4..c21e1dca4581f3f3b7fb73c3c4dd97be0eb55946 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JumlahModel.java
@@ -1,9 +1,13 @@
 package apap.tugasakhir.RumahSehat.models;
 
 import java.io.Serializable;
+import java.util.Optional;
 
+import javax.persistence.EmbeddedId;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
@@ -13,6 +17,8 @@ import javax.validation.constraints.NotNull;
 import org.hibernate.annotations.OnDelete;
 import org.hibernate.annotations.OnDeleteAction;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -27,13 +33,17 @@ import lombok.Setter;
 public class JumlahModel implements Serializable {
     
     @Id
-    @ManyToOne(fetch = FetchType.EAGER, optional=false)
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long idJumlah;
+    
+    @JsonIgnore
+    @ManyToOne(fetch = FetchType.EAGER, optional=true)
     @JoinColumn(name = "id_obat", referencedColumnName = "id")
     @OnDelete(action = OnDeleteAction.CASCADE)
     private ObatModel obat;
 
-    @Id
-    @ManyToOne(fetch = FetchType.EAGER, optional=false)
+    @JsonIgnore
+    @ManyToOne(fetch = FetchType.EAGER, optional=true)
     @JoinColumn(name = "id_resep", referencedColumnName = "id")
     @OnDelete(action = OnDeleteAction.CASCADE)
     private ResepModel resep;
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..74e863638adced8cace6a6d6ddce196f8d5bd8d2
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtRequest.java
@@ -0,0 +1,19 @@
+package apap.tugasakhir.RumahSehat.models;
+
+
+import java.io.Serializable;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@AllArgsConstructor
+public class JwtRequest implements Serializable{
+    
+    private static final long serialVersionUID = 5926468583005150707L;
+    
+    private String username;
+    private String password;
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a80c2eb69487cf875d8f7aae8454b2303d40689
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/JwtResponse.java
@@ -0,0 +1,17 @@
+package apap.tugasakhir.RumahSehat.models;
+
+import java.io.Serializable;
+
+public class JwtResponse implements Serializable {
+
+	private static final long serialVersionUID = -8091879091924046844L;
+	private final String jwttoken;
+
+	public JwtResponse(String jwttoken) {
+		this.jwttoken = jwttoken;
+	}
+
+	public String getToken() {
+		return this.jwttoken;
+	}
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java
index 9a437031818921571dd6a42decf05f397da64b29..6c78f828cd7827577855ba45895fcef2547f6787 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ObatModel.java
@@ -15,6 +15,7 @@ import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 
+import org.hibernate.annotations.ColumnDefault;
 import org.hibernate.annotations.GenericGenerator;
 
 import lombok.AllArgsConstructor;
@@ -41,7 +42,8 @@ public class ObatModel implements Serializable{
     private String nama;
 
     @NotNull
-    private Integer stok = 100;
+    @ColumnDefault("100")
+    private Integer Stok;
 
     @NotNull
     private Integer harga;
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java
index 9dd82796c2ced169aad29c9020fbd7e323eea98e..4a2fbce72b651e15e778ac60680962dfe001633b 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/PasienModel.java
@@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+import lombok.experimental.SuperBuilder;
 
 import javax.persistence.*;
 import javax.validation.constraints.NotNull;
@@ -16,6 +17,7 @@ import java.util.List;
 @Getter
 @AllArgsConstructor
 @NoArgsConstructor
+@SuperBuilder
 @Entity
 @Table(name = "pasien")
 public class PasienModel extends UserModel implements Serializable {
@@ -25,7 +27,6 @@ public class PasienModel extends UserModel implements Serializable {
     private Integer saldo;
 
     @NotNull
-    @Size(max = 3)
     @Column(name = "umur", nullable = false)
     private Integer umur;
 
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java
index 6d44099ec4ea2aa31079ff8e31bcd8b6f1a25d37..590f3697fcc0dcce3fda6d77ed5da5fed60678e9 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/ResepModel.java
@@ -4,10 +4,15 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+
+import org.hibernate.annotations.ColumnDefault;
 import org.hibernate.annotations.OnDelete;
 import org.hibernate.annotations.OnDeleteAction;
 import org.springframework.format.annotation.DateTimeFormat;
 import javax.persistence.*;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import javax.validation.constraints.NotNull;
 
 import java.io.Serializable;
@@ -21,7 +26,7 @@ import java.util.List;
 @NoArgsConstructor
 @Entity
 @Table(name = "resep")
-public class ResepModel  implements Serializable {
+public class ResepModel implements Serializable {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -30,6 +35,7 @@ public class ResepModel  implements Serializable {
 
     @NotNull
     @Column(name = "is_done", nullable = false)
+    @ColumnDefault("false")
     private Boolean isDone;
     
     @NotNull
@@ -37,11 +43,18 @@ public class ResepModel  implements Serializable {
     @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
     private LocalDateTime createdAt;
 
-    @ManyToOne(fetch = FetchType.EAGER, optional = false)
-    @JoinColumn(name = "confirmer_uuid", referencedColumnName = "uuid", nullable = false)
+    @ManyToOne(fetch = FetchType.EAGER, optional = true)
+    @JoinColumn(name = "confirmer_uuid", referencedColumnName = "uuid")
     @OnDelete(action = OnDeleteAction.CASCADE)
     private ApotekerModel apoteker;
 
+    @JsonIgnore
     @OneToMany(mappedBy = "resep", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     List<JumlahModel> listJumlah;
+
+    // @JsonIgnore
+    @OneToOne(mappedBy = "resep")
+    private AppointmentModel appointment;
+
+
 }
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java
index 09c25ae082aee0c1787f799b4838819df8681d72..59612d8420432b1731bc3ed03e52d54d1fe6ef5b 100644
--- a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/models/UserModel.java
@@ -3,6 +3,8 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
+import lombok.experimental.SuperBuilder;
+
 import org.hibernate.annotations.GenericGenerator;
 import javax.persistence.*;
 import javax.validation.constraints.NotNull;
@@ -13,7 +15,9 @@ import java.io.Serializable;
 @Getter
 @AllArgsConstructor
 @NoArgsConstructor
-@MappedSuperclass
+@SuperBuilder
+@Entity
+@Inheritance(strategy = InheritanceType.JOINED)
 public class UserModel implements Serializable {
     
     @Id
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd3c62b2efd20e7b1a9bfaa8dd306157ec18f767
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/AdminDb.java
@@ -0,0 +1,14 @@
+package apap.tugasakhir.RumahSehat.repository;
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import apap.tugasakhir.RumahSehat.models.AdminModel;
+import apap.tugasakhir.RumahSehat.models.UserModel;
+
+@Repository
+public interface AdminDb extends JpaRepository<AdminModel, Long> {
+    List<AdminModel> findAll();
+    AdminModel findByUsername(String username);
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d1688c3c9d644bf00b301dc1a4f65c8d5e08486
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/PasienDb.java
@@ -0,0 +1,14 @@
+package apap.tugasakhir.RumahSehat.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+import apap.tugasakhir.RumahSehat.models.PasienModel;
+
+@Repository
+public interface PasienDb extends JpaRepository<PasienModel, String> {
+  PasienModel findByUsername(String username);
+  PasienModel findByEmail(String email);
+  List<PasienModel> findAll();
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9cc08b608219428a693fdb72dcaaf38f0c29465
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/repository/UserDb.java
@@ -0,0 +1,14 @@
+package apap.tugasakhir.RumahSehat.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import apap.tugasakhir.RumahSehat.models.UserModel;
+
+@Repository
+public interface UserDb extends JpaRepository<UserModel, Long> {
+    List<UserModel> findAll();
+    UserModel findByUsername(String username);
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a460777fa2894b764d3eecdd94326138a06a990a
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/restController/PasienRestController.java
@@ -0,0 +1,81 @@
+package apap.tugasakhir.RumahSehat.restController;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+import org.apache.tomcat.util.http.parser.Authorization;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.server.ResponseStatusException;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import static org.springframework.http.HttpHeaders.AUTHORIZATION;
+import static org.springframework.http.HttpStatus.FORBIDDEN;
+
+import apap.tugasakhir.RumahSehat.models.PasienModel;
+import apap.tugasakhir.RumahSehat.service.PasienRestService;
+
+@RestController
+@RequestMapping("api/v1/pasien")
+public class PasienRestController {
+    @Autowired
+    private PasienRestService pasienRestService;
+
+    @PostMapping(value = "/register")
+    private ResponseEntity createPengajar(@RequestBody PasienModel pasien, BindingResult bindingResult) {
+        try {
+            if (bindingResult.hasFieldErrors()) {
+                throw new ResponseStatusException(
+                        HttpStatus.BAD_REQUEST, "Request body has invalid type or missing field.");
+            } else {
+                pasien.setListAppointment(new ArrayList<>());
+                pasien.setRole("Pasien");
+                pasien.setSaldo(0);
+                pasien.setIsSso(false);
+                ;
+                pasien.setPassword(pasienRestService.encrypt(pasien.getPassword()));
+                PasienModel newPasien = pasienRestService.addPasien(pasien);
+
+                HashMap<String, Object> response = new HashMap<>();
+                response.put("status", "success");
+                response.put("message", "registrasi pasien berhasil");
+                response.put("status_code", 200);
+                response.put("data", newPasien);
+                return ResponseEntity.ok(response);
+            }
+        } catch (Exception e) {
+            HashMap<String, Object> response = new HashMap<>();
+            response.put("status", "failed");
+            response.put("message", "registrasi pasien gagal");
+            response.put("status_code", 500);
+            response.put("data", null);
+            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
+        }
+    }
+
+    @GetMapping(value = "/list-pasien")
+    private List<PasienModel> retrieveListCourse() {
+        return pasienRestService.retrieveListPasien();
+    }
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc5146b7d865cecc1225748b7d3e13ebba6f1b05
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/UserDetailsServiceImpl.java
@@ -0,0 +1,30 @@
+package apap.tugasakhir.RumahSehat.security;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import apap.tugasakhir.RumahSehat.models.UserModel;
+import apap.tugasakhir.RumahSehat.repository.UserDb;
+
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+    @Autowired
+    private UserDb userDb;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        UserModel user = userDb.findByUsername(username);
+        Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
+        grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole()));
+        return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
+    }
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java
new file mode 100644
index 0000000000000000000000000000000000000000..0986e6f97fdb647e9430979e06fa1ba6dc7cf2a9
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/Attributes.java
@@ -0,0 +1,20 @@
+package apap.tugasakhir.RumahSehat.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@Setter
+@Getter
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Attributes {
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String ldap_cn;
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String kd_org;
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String nama;
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..e395caf48d47f88b126ae0fcba1f29038ada9b2c
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/AuthenticationSuccess.java
@@ -0,0 +1,19 @@
+package apap.tugasakhir.RumahSehat.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@Setter
+@Getter
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AuthenticationSuccess {
+    @XmlElement(name = "user", namespace = "http://www.yale.edu/tp/cas")
+    private String user;
+    
+    @XmlElement(name = "attributes", namespace = "http://www.yale.edu/tp/cas")
+    private Attributes attributes;
+
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd2b0bc8a07c843ea8f85168c5a7d929c3603f80
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/security/xml/ServiceResponse.java
@@ -0,0 +1,21 @@
+package apap.tugasakhir.RumahSehat.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+@Setter
+@Getter
+@XmlRootElement(name = "serviceResponse", namespace = "http://www.yale.edu/tp/cas")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceResponse {
+    @XmlElement(name = "authenticationFailure", namespace = "http://www.yale.edu/tp/cas")
+    private String authenticationFailure;
+    @XmlElement(name = "authenticationSuccess", namespace = "http://www.yale.edu/tp/cas")
+    private AuthenticationSuccess authenticationSuccess;
+}
\ No newline at end of file
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java
new file mode 100644
index 0000000000000000000000000000000000000000..520e04510f62b401ea30d5c74e088d96b43cca54
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminService.java
@@ -0,0 +1,12 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import apap.tugasakhir.RumahSehat.models.AdminModel;
+
+public interface AdminService {
+    AdminModel addUser(AdminModel user);
+    public String encrypt(String password);
+    AdminModel getUserByUsername(String name);
+    List<AdminModel> findAll();
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc59e69f0c1de24be8845779eb960418788d34a4
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/AdminServiceImpl.java
@@ -0,0 +1,40 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import apap.tugasakhir.RumahSehat.models.AdminModel;
+import apap.tugasakhir.RumahSehat.repository.AdminDb;
+
+@Service
+public class AdminServiceImpl implements AdminService {
+    @Autowired
+    private AdminDb adminDb;
+
+    @Override
+    public AdminModel addUser(AdminModel user) {
+        String pass = encrypt(user.getPassword());
+        user.setPassword(pass);
+        return adminDb.save(user);
+    }
+
+    @Override
+    public String encrypt(String password) {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        String hashedPassword = passwordEncoder.encode(password);
+        return hashedPassword;
+    }
+
+    @Override
+    public AdminModel getUserByUsername(String username) {
+        return adminDb.findByUsername(username);
+    }
+
+    @Override
+    public List<AdminModel> findAll() {
+        return adminDb.findAll();
+    }
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c389af7234728185563dfcfa8144b6183926fa1
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestService.java
@@ -0,0 +1,15 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import apap.tugasakhir.RumahSehat.models.PasienModel;
+
+public interface PasienRestService {
+    PasienModel addPasien(PasienModel pasien);
+
+    List<PasienModel> retrieveListPasien();
+
+    String encrypt(String password);
+
+    PasienModel getPasien(String username);
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1537139901646f8f65f79bfa3b5cb7d279f7de71
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/PasienRestServiceImpl.java
@@ -0,0 +1,54 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import javax.transaction.Transactional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import apap.tugasakhir.RumahSehat.models.PasienModel;
+import apap.tugasakhir.RumahSehat.repository.PasienDb;
+
+@Service
+@Transactional
+public class PasienRestServiceImpl implements PasienRestService{
+
+    @Autowired
+    private PasienDb pasienDb;
+
+    @Override
+    public PasienModel addPasien(PasienModel pasien){
+        pasien.setPassword(encrypt(pasien.getPassword()));
+
+        if (pasienDb.findByUsername(pasien.getUsername()) != null) {
+            throw new RuntimeException("Username " + pasien.getUsername() + " sudah terdaftar");
+        }
+
+
+        if (pasienDb.findByEmail(pasien.getEmail()) != null) {
+            throw new RuntimeException("Email " + pasien.getEmail() + " sudah terdaftar");
+        }
+
+        return pasienDb.save(pasien);
+    }
+
+    @Override
+    public List<PasienModel> retrieveListPasien(){
+        return pasienDb.findAll();
+    }
+
+    @Override
+    public String encrypt(String password) {
+      BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+      String hashedPassword = passwordEncoder.encode(password);
+      return hashedPassword;
+    }
+
+    @Override
+    public PasienModel getPasien(String username) {
+        return pasienDb.findByUsername(username);
+    }
+
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..23bf8abb083422e0f8bf64153b4a8e23dafc0cb7
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserService.java
@@ -0,0 +1,12 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import apap.tugasakhir.RumahSehat.models.UserModel;
+
+public interface UserService {
+    UserModel addUser(UserModel user);
+    public String encrypt(String password);
+    UserModel getUserByUsername(String name);
+    List<UserModel> findAll();
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f8fb6748987e6a8e91c0939c8087a7c4a510d74
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/service/UserServiceImpl.java
@@ -0,0 +1,40 @@
+package apap.tugasakhir.RumahSehat.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import apap.tugasakhir.RumahSehat.models.UserModel;
+import apap.tugasakhir.RumahSehat.repository.UserDb;
+
+@Service
+public class UserServiceImpl implements UserService {
+    @Autowired
+    private UserDb userDb;
+
+    @Override
+    public UserModel addUser(UserModel user) {
+        String pass = encrypt(user.getPassword());
+        user.setPassword(pass);
+        return userDb.save(user);
+    }
+
+    @Override
+    public String encrypt(String password) {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        String hashedPassword = passwordEncoder.encode(password);
+        return hashedPassword;
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username) {
+        return userDb.findByUsername(username);
+    }
+
+    @Override
+    public List<UserModel> findAll() {
+        return userDb.findAll();
+    }
+}
diff --git a/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff61b35c09e4f16faa988fef783f58f5f3830cc6
--- /dev/null
+++ b/backend/RumahSehat/src/main/java/apap/tugasakhir/RumahSehat/setting/Setting.java
@@ -0,0 +1,13 @@
+package apap.tugasakhir.RumahSehat.setting;
+
+public class Setting {
+    final public static String CLIENT_BASE_URL = "http://localhost:2020";
+    final public static String CLIENT_LOGIN = CLIENT_BASE_URL + "/validate-ticket";
+    final public static String CLIENT_LOGOUT = CLIENT_BASE_URL + "/logout";
+    final public static String SERVER_BASE_URL = "https://sso.ui.ac.id/cas2";
+    final public static String SERVER_LOGIN = SERVER_BASE_URL + "/login?service=";
+    final public static String SERVER_LOGOUT = SERVER_BASE_URL + "/logout?url=";
+    final public static String SERVER_VALIDATE_TICKET
+        = SERVER_BASE_URL + "/serviceValidate?ticket=%s&service=%s";
+}
+
diff --git a/backend/RumahSehat/src/main/resources/application.properties b/backend/RumahSehat/src/main/resources/application.properties
index 6515465659c67cc916fcd5f4e42f7b4bf65674ae..372833d5a9becf1edd83e10335760be37c9973bf 100644
--- a/backend/RumahSehat/src/main/resources/application.properties
+++ b/backend/RumahSehat/src/main/resources/application.properties
@@ -13,6 +13,6 @@ spring.datasource.password=
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
 
 #pembuatan database (create || create drop || validate || update)
-spring.jpa.hibernate.ddl-auto=create
+spring.jpa.hibernate.ddl-auto=create-drop
 
 server.port=2020
diff --git a/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart b/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ba0130b338397b3f170b5400b01a68bbce0bc2da
--- /dev/null
+++ b/frontend/rumah_sehat/lib/features/registrasi_pasien/registrasi_pasien.dart
@@ -0,0 +1,133 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+import 'package:http/http.dart' as http;
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
+
+class SignUpPage extends StatefulWidget {
+  const SignUpPage({Key? key}) : super(key: key);
+
+  @override
+  State<SignUpPage> createState() => _SignUpPageState();
+}
+
+class _SignUpPageState extends State<SignUpPage> {
+  final TextEditingController _usernameController = TextEditingController();
+  final TextEditingController _passwordController = TextEditingController();
+  final TextEditingController _nameController = TextEditingController();
+  final TextEditingController _emailController = TextEditingController();
+  final TextEditingController _umurController = TextEditingController();
+
+  void displayDialog(context, title, text) => showDialog(
+    context: context,
+    builder: (context) =>
+        AlertDialog(
+            title: Text(title),
+            content: Text(text)
+        ),
+  );
+
+
+  Future<http.Response> attemptSignUp(String username, String password, String umur, String name, String email) async {
+    // String? access_token_await = await storage.read(key: "access_token");
+    // String access_token = "";
+    // if(access_token_await != null){
+    //   access_token = access_token_await;
+    // }
+    var res = await http.post(
+        Uri.parse('http://localhost:2020/api/v1/pasien/register'),
+        headers: <String, String>{"Content-Type": "application/json",
+          // "Authorization": "Bearer " + access_token,
+          "Accept": "application/json"},
+        body: jsonEncode(<String, String>{
+          "nama": name,
+          "email": email,
+          "umur": umur,
+          "username": username,
+          "password": password
+        })
+    );
+    return res;
+  }
+
+
+
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        appBar: AppBar(title: Text("Sign Up"),),
+        body: Padding(
+          padding: const EdgeInsets.all(8.0),
+          child: Column(
+            children: <Widget>[
+              TextField(
+                controller: _usernameController,
+                decoration: InputDecoration(
+                    labelText: 'Username'
+                ),
+              ),
+              TextField(
+                controller: _passwordController,
+                obscureText: true,
+                decoration: InputDecoration(
+                    labelText: 'Password'
+                ),
+              ),
+              TextField(
+                controller: _emailController,
+                decoration: InputDecoration(
+                    labelText: 'Email'
+                ),
+              ),
+              TextField(
+                controller: _nameController,
+                decoration: InputDecoration(
+                    labelText: 'Nama'
+                ),
+              ),
+              TextField(
+                controller: _umurController,
+                keyboardType: TextInputType.number,
+                decoration: InputDecoration(
+                    labelText: 'Umur'
+                ),
+              ),
+              SizedBox(
+                  height: 20
+              ),
+              TextButton(
+                style: ButtonStyle(
+                  backgroundColor: MaterialStatePropertyAll<Color>(Colors.green),
+                ),
+                onPressed: () async {
+                  var response = await attemptSignUp(_usernameController.text, _passwordController.text, _umurController.text, _nameController.text, _emailController.text);
+                  print(response.statusCode);
+                  if(response.statusCode == 200) {
+                    displayDialog(context, "Sign Up success", "Sign Up success");
+                    //JWT.fromJson(jsonDecode(jwt.body));
+                    // Navigator.push(
+                    //     context,
+                    //     MaterialPageRoute(
+                    //         builder: (context) => HomePage.fromBase64(jwt)
+                    //     )
+                    // );
+                  } else if(response.statusCode == 400){
+                    displayDialog(context, "An Error Occurred", "Request body has invalid type or missing field.");
+                  } else if(response.statusCode == 403) {
+                    displayDialog(context, "An Error Occurred", "Forbidden");
+                  } else {
+                    displayDialog(context, "An Error Occurred", "No account was found matching that username and password");
+                  }
+                },
+                child: Text(
+                  "submit",
+                  style: TextStyle(color: Colors.white),
+                ),
+              )
+            ],
+          ),
+        )
+    );
+  }
+}
\ No newline at end of file
diff --git a/frontend/rumah_sehat/lib/main.dart b/frontend/rumah_sehat/lib/main.dart
index b35e788a9fbc6184db1a4b240f6212e1be512cbc..abf973782e20378f46490c8ce5539c928e6aa648 100644
--- a/frontend/rumah_sehat/lib/main.dart
+++ b/frontend/rumah_sehat/lib/main.dart
@@ -1,26 +1,130 @@
+import 'dart:convert';
+
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:rumah_sehat/core/routes.dart';
+import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 import 'package:rumah_sehat/core/theme.dart';
+import 'package:flutter/material.dart';
+import 'package:http/http.dart' as http;
+import 'package:rumah_sehat/features/registrasi_pasien/registrasi_pasien.dart';
+
+const SERVER_IP = 'http://localhost:8080';
+final storage = FlutterSecureStorage();
 
 void main() {
   runApp(
-    const ProviderScope(
+    ProviderScope(
       child: RumahSehatApp(),
     ),
   );
 }
 
 class RumahSehatApp extends StatelessWidget {
-  const RumahSehatApp({Key? key}) : super(key: key);
+  const RumahSehatApp({super.key});
+
+  // This widget is the root of your application.
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
-      debugShowCheckedModeBanner: false,
-      title: 'RumahSehat',
-      theme: RumahSehatTheme.theme,
-      routes: Routes.route,
-      initialRoute: Routes.home,
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        // This is the theme of your application.
+        //
+        // Try running your application with "flutter run". You'll see the
+        // application has a blue toolbar. Then, without quitting the app, try
+        // changing the primarySwatch below to Colors.green and then invoke
+        // "hot reload" (press "r" in the console where you ran "flutter run",
+        // or simply save your changes to "hot reload" in a Flutter IDE).
+        // Notice that the counter didn't reset back to zero; the application
+        // is not restarted.
+        primarySwatch: Colors.blue,
+      ),
+      home: LoginPage(),
+    );
+  }
+}
+
+class LoginPage extends StatelessWidget {
+  LoginPage({super.key});
+  final TextEditingController _usernameController = TextEditingController();
+  final TextEditingController _passwordController = TextEditingController();
+
+  void displayDialog(context, title, text) => showDialog(
+      context: context,
+      builder: (context) =>
+        AlertDialog(
+          title: Text(title),
+          content: Text(text)
+        ),
+    );
+
+  Future<http.Response> attemptLogIn(String username, String password) async {
+    var res = await http.post(
+        Uri.parse('http://localhost:2020/api/login'),
+        headers: <String, String>{"Content-Type": "application/x-www-form-urlencoded"},
+        body: {
+          "username": username,
+          "password": password
+        }
+    );
+    return res;
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(title: Text("Log In"),),
+      body: Padding(
+        padding: const EdgeInsets.all(8.0),
+        child: Column(
+          children: <Widget>[
+            TextField(
+              controller: _usernameController,
+              decoration: InputDecoration(
+                labelText: 'Username'
+              ),
+            ),
+            TextField(
+              controller: _passwordController,
+              obscureText: true,
+              decoration: InputDecoration(
+                labelText: 'Password'
+              ),
+            ),
+            TextButton(
+              onPressed: () async {
+                var username = _usernameController.text;
+                var password = _passwordController.text;
+                var jwt = await attemptLogIn(username, password);
+                if(jwt != null) {
+                  //storage.write(key: "jwt", value: jwt);
+                  // Navigator.push(
+                  //   context,
+                  //   MaterialPageRoute(
+                  //     builder: (context) => HomePage.fromBase64(jwt)
+                  //   )
+                  // );
+                } else {
+                  displayDialog(context, "An Error Occurred", "No account was found matching that username and password");
+                }
+              },
+              child: Text("Log In")
+            ),
+            TextButton(
+              onPressed: () {
+                Navigator.push(
+                    context,
+                    MaterialPageRoute(
+                        builder: (context) => SignUpPage()
+                    )
+                );
+              },
+              child: Text("Sign Up")
+            )
+          ],
+        ),
+      )
     );
   }
 }
diff --git a/frontend/rumah_sehat/lib/models/pasien_model.dart b/frontend/rumah_sehat/lib/models/pasien_model.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7bad327219134bdc723c6df7ccf1d83a22723183
--- /dev/null
+++ b/frontend/rumah_sehat/lib/models/pasien_model.dart
@@ -0,0 +1,12 @@
+// class PasienModel {
+//   final String ;
+//   final String nama;
+//   final String instruction;
+//   final String photoUrl;
+
+//   PasienModel.fromJson(Map<String, dynamic> data)
+//       : name = data['strMeal'],
+//         area = data['strArea'],
+//         instruction = data['strInstructions'],
+//         photoUrl = data['strMealThumb'];
+// }
\ No newline at end of file
diff --git a/frontend/rumah_sehat/pubspec.lock b/frontend/rumah_sehat/pubspec.lock
index 736f6c8413ca89dde28643946c5e0ec33ee9e5a1..cdaee1da7a7035dc09de36d45e90c3b812806710 100644
--- a/frontend/rumah_sehat/pubspec.lock
+++ b/frontend/rumah_sehat/pubspec.lock
@@ -90,6 +90,48 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.1.1"
+  flutter_secure_storage:
+    dependency: "direct main"
+    description:
+      name: flutter_secure_storage
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "6.0.0"
+  flutter_secure_storage_linux:
+    dependency: transitive
+    description:
+      name: flutter_secure_storage_linux
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.2"
+  flutter_secure_storage_macos:
+    dependency: transitive
+    description:
+      name: flutter_secure_storage_macos
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.2"
+  flutter_secure_storage_platform_interface:
+    dependency: transitive
+    description:
+      name: flutter_secure_storage_platform_interface
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.1"
+  flutter_secure_storage_web:
+    dependency: transitive
+    description:
+      name: flutter_secure_storage_web
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.1"
+  flutter_secure_storage_windows:
+    dependency: transitive
+    description:
+      name: flutter_secure_storage_windows
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.3"
   flutter_test:
     dependency: "direct dev"
     description: flutter
@@ -100,6 +142,13 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
+  http:
+    dependency: "direct main"
+    description:
+      name: http
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.13.5"
   http_parser:
     dependency: transitive
     description:
diff --git a/frontend/rumah_sehat/pubspec.yaml b/frontend/rumah_sehat/pubspec.yaml
index 4b5fb1eb18a34a7b3b1cc797a68f546ecb2ce854..ba78c2d4011cc61613a28bab304a60f911fb10e9 100644
--- a/frontend/rumah_sehat/pubspec.yaml
+++ b/frontend/rumah_sehat/pubspec.yaml
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 version: 1.0.0+1
 
 environment:
-  sdk: ">=2.12.0 <3.0.0"
+  sdk: ">=2.17.0 <3.0.0"
 
 # Dependencies specify other packages that your package needs in order to work.
 # To automatically upgrade your package dependencies to the latest versions
@@ -37,6 +37,8 @@ dependencies:
   dio: ^4.0.6
   shared_preferences: ^2.0.15
   flutter_riverpod: ^2.1.1
+  flutter_secure_storage: ^6.0.0
+  http: ^0.13.5
 
 dev_dependencies:
   flutter_test: