diff --git a/api/src/main/java/com/databasir/api/OAuth2AppController.java b/api/src/main/java/com/databasir/api/OAuth2AppController.java
index 00d8ab8..0c67cde 100644
--- a/api/src/main/java/com/databasir/api/OAuth2AppController.java
+++ b/api/src/main/java/com/databasir/api/OAuth2AppController.java
@@ -1,17 +1,22 @@
 package com.databasir.api;
 
 import com.databasir.common.JsonData;
-import com.databasir.core.infrastructure.oauth2.OAuthAppService;
-import com.databasir.core.infrastructure.oauth2.OAuthHandler;
-import com.databasir.core.infrastructure.oauth2.data.OAuthAppResponse;
+import com.databasir.core.domain.app.OAuthAppService;
+import com.databasir.core.domain.app.data.*;
+import com.databasir.core.domain.app.handler.OAuthHandler;
 import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.util.List;
 
+import static org.springframework.data.domain.Sort.Direction.DESC;
+
 @Controller
 @RequiredArgsConstructor
 public class OAuth2AppController {
@@ -20,6 +25,9 @@ public class OAuth2AppController {
 
     private final OAuthAppService oAuthAppService;
 
+    /**
+     * 无需授权
+     */
     @GetMapping("/oauth2/authorization/{registrationId}")
     @ResponseBody
     public JsonData<String> authorization(@PathVariable String registrationId) {
@@ -27,10 +35,53 @@ public class OAuth2AppController {
         return JsonData.ok(authorization);
     }
 
+    /**
+     * 无需授权
+     */
     @GetMapping("/oauth2/apps")
     @ResponseBody
     public JsonData<List<OAuthAppResponse>> listApps() {
         return JsonData.ok(oAuthAppService.listAll());
     }
 
+    @GetMapping(Routes.OAuth2App.LIST_PAGE)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
+    @ResponseBody
+    public JsonData<Page<OAuthAppPageResponse>> listPage(@PageableDefault(sort = "id", direction = DESC)
+                                                                 Pageable page,
+                                                         OAuthAppPageCondition condition) {
+        return JsonData.ok(oAuthAppService.listPage(page, condition));
+    }
+
+    @GetMapping(Routes.OAuth2App.GET_ONE)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
+    @ResponseBody
+    public JsonData<OAuthAppDetailResponse> getOne(@PathVariable Integer id) {
+        return JsonData.ok(oAuthAppService.getOne(id));
+
+    }
+
+    @PostMapping(Routes.OAuth2App.CREATE)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
+    @ResponseBody
+    public JsonData<Integer> create(@RequestBody @Valid OAuthAppCreateRequest request) {
+        Integer id = oAuthAppService.create(request);
+        return JsonData.ok(id);
+    }
+
+    @PatchMapping(Routes.OAuth2App.UPDATE)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
+    @ResponseBody
+    public JsonData<Void> updateById(@RequestBody @Valid OAuthAppUpdateRequest request) {
+        oAuthAppService.updateById(request);
+        return JsonData.ok();
+    }
+
+    @DeleteMapping(Routes.OAuth2App.DELETE)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
+    @ResponseBody
+    public JsonData<Void> deleteById(@PathVariable Integer id) {
+        oAuthAppService.deleteById(id);
+        return JsonData.ok();
+    }
 }
diff --git a/api/src/main/java/com/databasir/api/OperationLogController.java b/api/src/main/java/com/databasir/api/OperationLogController.java
index 7345735..7c0e94f 100644
--- a/api/src/main/java/com/databasir/api/OperationLogController.java
+++ b/api/src/main/java/com/databasir/api/OperationLogController.java
@@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.web.PageableDefault;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -21,6 +22,7 @@ public class OperationLogController {
     private final OperationLogService operationLogService;
 
     @GetMapping(Routes.OperationLog.LIST)
+    @PreAuthorize("hasAnyAuthority('SYS_OWNER')")
     public JsonData<Page<OperationLogPageResponse>> list(@PageableDefault(sort = "id", direction = Sort.Direction.DESC)
                                                                  Pageable page,
                                                          OperationLogPageCondition condition) {
diff --git a/api/src/main/java/com/databasir/api/Routes.java b/api/src/main/java/com/databasir/api/Routes.java
index 1aac6c9..a4aefbc 100644
--- a/api/src/main/java/com/databasir/api/Routes.java
+++ b/api/src/main/java/com/databasir/api/Routes.java
@@ -110,4 +110,18 @@ public interface Routes {
     interface OperationLog {
         String LIST = BASE + "/operation_logs";
     }
+
+    interface OAuth2App {
+
+        String LIST_PAGE = BASE + "/oauth2_apps";
+
+        String CREATE = BASE + "/oauth2_apps";
+
+        String UPDATE = BASE + "/oauth2_apps";
+
+        String DELETE = BASE + "/oauth2_apps/{id}";
+
+        String GET_ONE = BASE + "/oauth2_apps/{id}";
+
+    }
 }
diff --git a/api/src/main/java/com/databasir/api/config/oauth2/DatabasirOauth2LoginFilter.java b/api/src/main/java/com/databasir/api/config/oauth2/DatabasirOauth2LoginFilter.java
index 798b7b7..4dd5140 100644
--- a/api/src/main/java/com/databasir/api/config/oauth2/DatabasirOauth2LoginFilter.java
+++ b/api/src/main/java/com/databasir/api/config/oauth2/DatabasirOauth2LoginFilter.java
@@ -2,7 +2,7 @@ package com.databasir.api.config.oauth2;
 
 import com.databasir.api.config.security.DatabasirUserDetailService;
 import com.databasir.core.domain.user.data.UserDetailResponse;
-import com.databasir.core.infrastructure.oauth2.OAuthAppService;
+import com.databasir.core.domain.app.OAuthAppService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.authentication.AuthenticationManager;
diff --git a/api/src/main/java/com/databasir/api/config/security/DatabasirAuthenticationFailureHandler.java b/api/src/main/java/com/databasir/api/config/security/DatabasirAuthenticationFailureHandler.java
index dfd0554..5c291eb 100644
--- a/api/src/main/java/com/databasir/api/config/security/DatabasirAuthenticationFailureHandler.java
+++ b/api/src/main/java/com/databasir/api/config/security/DatabasirAuthenticationFailureHandler.java
@@ -1,6 +1,6 @@
 package com.databasir.api.config.security;
 
-import com.databasir.core.infrastructure.oauth2.exception.DatabasirAuthenticationException;
+import com.databasir.core.domain.app.exception.DatabasirAuthenticationException;
 import com.databasir.common.JsonData;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.RequiredArgsConstructor;
diff --git a/core/src/main/java/com/databasir/core/domain/DomainErrors.java b/core/src/main/java/com/databasir/core/domain/DomainErrors.java
index decc75b..606361f 100644
--- a/core/src/main/java/com/databasir/core/domain/DomainErrors.java
+++ b/core/src/main/java/com/databasir/core/domain/DomainErrors.java
@@ -24,7 +24,8 @@ public enum DomainErrors implements DatabasirErrors {
     CANNOT_UPDATE_SELF_ROLE("A_10009", "无法对自己执行角色变更的操作"),
     UPDATE_PASSWORD_CONFIRM_FAILED("A_10010", "两次密码输入不一致"),
     ORIGIN_PASSWORD_NOT_CORRECT("A_10011", "原密码不正确"),
-    INVALID_CRON_EXPRESSION("A_10012", "不合法的 cron 表达式");
+    INVALID_CRON_EXPRESSION("A_10012", "不合法的 cron 表达式"),
+    REGISTRATION_ID_DUPLICATE("A_10013", "应用注册 ID 不能重复");
 
     private final String errCode;
 
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthAppService.java b/core/src/main/java/com/databasir/core/domain/app/OAuthAppService.java
similarity index 57%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthAppService.java
rename to core/src/main/java/com/databasir/core/domain/app/OAuthAppService.java
index 8acfe44..f71259b 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthAppService.java
+++ b/core/src/main/java/com/databasir/core/domain/app/OAuthAppService.java
@@ -1,18 +1,27 @@
-package com.databasir.core.infrastructure.oauth2;
+package com.databasir.core.domain.app;
 
+import com.databasir.core.domain.DomainErrors;
+import com.databasir.core.domain.app.converter.OAuthAppPojoConverter;
+import com.databasir.core.domain.app.converter.OAuthAppResponseConverter;
+import com.databasir.core.domain.app.data.*;
+import com.databasir.core.domain.app.handler.OAuthHandler;
+import com.databasir.core.domain.app.handler.OAuthProcessContext;
+import com.databasir.core.domain.app.handler.OAuthProcessResult;
 import com.databasir.core.domain.user.data.UserCreateRequest;
 import com.databasir.core.domain.user.data.UserDetailResponse;
 import com.databasir.core.domain.user.service.UserService;
-import com.databasir.core.infrastructure.oauth2.converter.OAuthAppResponseConverter;
-import com.databasir.core.infrastructure.oauth2.data.OAuthAppResponse;
 import com.databasir.dao.impl.OAuthAppDao;
 import com.databasir.dao.tables.pojos.OauthAppPojo;
 import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -28,6 +37,8 @@ public class OAuthAppService {
 
     private final OAuthAppResponseConverter oAuthAppResponseConverter;
 
+    private final OAuthAppPojoConverter oAuthAppPojoConverter;
+
     public UserDetailResponse oauthCallback(String registrationId, Map<String, String[]> params) {
 
         // match handler
@@ -66,4 +77,35 @@ public class OAuthAppService {
                 .collect(Collectors.toList());
     }
 
+    public void deleteById(Integer id) {
+        if (oAuthAppDao.existsById(id)) {
+            oAuthAppDao.deleteById(id);
+        }
+    }
+
+    public void updateById(OAuthAppUpdateRequest request) {
+        OauthAppPojo pojo = oAuthAppPojoConverter.of(request);
+        try {
+            oAuthAppDao.updateById(pojo);
+        } catch (DuplicateKeyException e) {
+            throw DomainErrors.REGISTRATION_ID_DUPLICATE.exception();
+        }
+    }
+
+    public Integer create(OAuthAppCreateRequest request) {
+        OauthAppPojo pojo = oAuthAppPojoConverter.of(request);
+        try {
+            return oAuthAppDao.insertAndReturnId(pojo);
+        } catch (DuplicateKeyException e) {
+            throw DomainErrors.REGISTRATION_ID_DUPLICATE.exception();
+        }
+    }
+
+    public Page<OAuthAppPageResponse> listPage(Pageable page, OAuthAppPageCondition condition) {
+        return oAuthAppDao.selectByPage(page, condition.toCondition()).map(oAuthAppPojoConverter::toPageResponse);
+    }
+
+    public Optional<OAuthAppDetailResponse> getOne(Integer id) {
+        return oAuthAppDao.selectOptionalById(id).map(oAuthAppPojoConverter::toDetailResponse);
+    }
 }
diff --git a/core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppPojoConverter.java b/core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppPojoConverter.java
new file mode 100644
index 0000000..1d6aed2
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppPojoConverter.java
@@ -0,0 +1,26 @@
+package com.databasir.core.domain.app.converter;
+
+import com.databasir.core.domain.app.data.OAuthAppCreateRequest;
+import com.databasir.core.domain.app.data.OAuthAppDetailResponse;
+import com.databasir.core.domain.app.data.OAuthAppPageResponse;
+import com.databasir.core.domain.app.data.OAuthAppUpdateRequest;
+import com.databasir.dao.tables.pojos.OauthAppPojo;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+@Mapper(componentModel = "spring")
+public interface OAuthAppPojoConverter {
+
+    @Mapping(target = "id", ignore = true)
+    @Mapping(target = "createAt", ignore = true)
+    @Mapping(target = "updateAt", ignore = true)
+    OauthAppPojo of(OAuthAppCreateRequest request);
+
+    @Mapping(target = "createAt", ignore = true)
+    @Mapping(target = "updateAt", ignore = true)
+    OauthAppPojo of(OAuthAppUpdateRequest request);
+
+    OAuthAppPageResponse toPageResponse(OauthAppPojo pojo);
+
+    OAuthAppDetailResponse toDetailResponse(OauthAppPojo pojo);
+}
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/converter/OAuthAppResponseConverter.java b/core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppResponseConverter.java
similarity index 61%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/converter/OAuthAppResponseConverter.java
rename to core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppResponseConverter.java
index e1114b6..18e5f9b 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/converter/OAuthAppResponseConverter.java
+++ b/core/src/main/java/com/databasir/core/domain/app/converter/OAuthAppResponseConverter.java
@@ -1,6 +1,6 @@
-package com.databasir.core.infrastructure.oauth2.converter;
+package com.databasir.core.domain.app.converter;
 
-import com.databasir.core.infrastructure.oauth2.data.OAuthAppResponse;
+import com.databasir.core.domain.app.data.OAuthAppResponse;
 import com.databasir.dao.tables.pojos.OauthAppPojo;
 import org.mapstruct.Mapper;
 
diff --git a/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppCreateRequest.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppCreateRequest.java
new file mode 100644
index 0000000..d898d23
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppCreateRequest.java
@@ -0,0 +1,35 @@
+package com.databasir.core.domain.app.data;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class OAuthAppCreateRequest {
+
+    @NotNull
+    private String registrationId;
+
+    @NotBlank
+    private String appName;
+
+    @NotBlank
+    private String appType;
+
+    private String appIcon;
+
+    @NotBlank
+    private String authUrl;
+
+    @NotBlank
+    private String resourceUrl;
+
+    @NotBlank
+    private String clientId;
+
+    @NotBlank
+    private String clientSecret;
+
+    private String scope;
+}
diff --git a/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppDetailResponse.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppDetailResponse.java
new file mode 100644
index 0000000..fc2428a
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppDetailResponse.java
@@ -0,0 +1,31 @@
+package com.databasir.core.domain.app.data;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class OAuthAppDetailResponse {
+
+    private Integer id;
+
+    private String appName;
+
+    private String appIcon;
+
+    private String appType;
+
+    private String registrationId;
+
+    private String clientId;
+
+    private String clientSecret;
+
+    private String authUrl;
+
+    private String resourceUrl;
+
+    private LocalDateTime updateAt;
+
+    private LocalDateTime createAt;
+}
diff --git a/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageCondition.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageCondition.java
new file mode 100644
index 0000000..94666f0
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageCondition.java
@@ -0,0 +1,30 @@
+package com.databasir.core.domain.app.data;
+
+import com.databasir.dao.Tables;
+import lombok.Data;
+import org.jooq.Condition;
+import org.jooq.impl.DSL;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class OAuthAppPageCondition {
+
+    private String appNameContains;
+
+    private String appType;
+
+    public Condition toCondition() {
+        List<Condition> conditions = new ArrayList<>();
+        if (appNameContains != null && !appNameContains.trim().equals("")) {
+            conditions.add(Tables.OAUTH_APP.APP_NAME.contains(appNameContains));
+        }
+        if (appType != null) {
+            conditions.add(Tables.OAUTH_APP.APP_TYPE.eq(appType));
+        }
+        return conditions.stream()
+                .reduce(Condition::and)
+                .orElse(DSL.trueCondition());
+    }
+}
diff --git a/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageResponse.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageResponse.java
new file mode 100644
index 0000000..46e27c8
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppPageResponse.java
@@ -0,0 +1,30 @@
+package com.databasir.core.domain.app.data;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class OAuthAppPageResponse {
+
+    private Integer id;
+
+    private String appName;
+
+    private String appIcon;
+
+    private String appType;
+
+    private String registrationId;
+
+    private String clientId;
+
+    private String authUrl;
+
+    private String resourceUrl;
+
+    private LocalDateTime updateAt;
+
+    private LocalDateTime createAt;
+
+}
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/data/OAuthAppResponse.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppResponse.java
similarity index 88%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/data/OAuthAppResponse.java
rename to core/src/main/java/com/databasir/core/domain/app/data/OAuthAppResponse.java
index d6579a1..c460aae 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/data/OAuthAppResponse.java
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppResponse.java
@@ -1,4 +1,4 @@
-package com.databasir.core.infrastructure.oauth2.data;
+package com.databasir.core.domain.app.data;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppUpdateRequest.java b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppUpdateRequest.java
new file mode 100644
index 0000000..0d633cd
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/app/data/OAuthAppUpdateRequest.java
@@ -0,0 +1,39 @@
+package com.databasir.core.domain.app.data;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class OAuthAppUpdateRequest {
+
+    @NotNull
+    private Integer id;
+
+    @NotBlank
+    private String registrationId;
+
+    @NotBlank
+    private String appName;
+
+    @NotBlank
+    private String appType;
+
+    private String appIcon;
+
+    @NotBlank
+    private String authUrl;
+
+    @NotBlank
+    private String resourceUrl;
+
+    @NotBlank
+    private String clientId;
+
+    @NotBlank
+    private String clientSecret;
+
+    private String scope;
+
+}
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/exception/DatabasirAuthenticationException.java b/core/src/main/java/com/databasir/core/domain/app/exception/DatabasirAuthenticationException.java
similarity index 90%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/exception/DatabasirAuthenticationException.java
rename to core/src/main/java/com/databasir/core/domain/app/exception/DatabasirAuthenticationException.java
index 5ba8e05..1d9986f 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/exception/DatabasirAuthenticationException.java
+++ b/core/src/main/java/com/databasir/core/domain/app/exception/DatabasirAuthenticationException.java
@@ -1,4 +1,4 @@
-package com.databasir.core.infrastructure.oauth2.exception;
+package com.databasir.core.domain.app.exception;
 
 import com.databasir.common.DatabasirException;
 import org.springframework.security.core.AuthenticationException;
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/GithubOauthHandler.java b/core/src/main/java/com/databasir/core/domain/app/handler/GithubOauthHandler.java
similarity index 95%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/GithubOauthHandler.java
rename to core/src/main/java/com/databasir/core/domain/app/handler/GithubOauthHandler.java
index 25460a9..71ad828 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/GithubOauthHandler.java
+++ b/core/src/main/java/com/databasir/core/domain/app/handler/GithubOauthHandler.java
@@ -1,8 +1,8 @@
-package com.databasir.core.infrastructure.oauth2;
+package com.databasir.core.domain.app.handler;
 
 
 import com.databasir.core.domain.DomainErrors;
-import com.databasir.core.infrastructure.oauth2.exception.DatabasirAuthenticationException;
+import com.databasir.core.domain.app.exception.DatabasirAuthenticationException;
 import com.databasir.core.infrastructure.remote.github.GithubRemoteService;
 import com.databasir.dao.enums.OAuthAppType;
 import com.databasir.dao.impl.OAuthAppDao;
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthHandler.java b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthHandler.java
similarity index 79%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthHandler.java
rename to core/src/main/java/com/databasir/core/domain/app/handler/OAuthHandler.java
index e0973fb..d8287a7 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthHandler.java
+++ b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthHandler.java
@@ -1,4 +1,4 @@
-package com.databasir.core.infrastructure.oauth2;
+package com.databasir.core.domain.app.handler;
 
 public interface OAuthHandler {
 
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessContext.java b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessContext.java
similarity index 88%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessContext.java
rename to core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessContext.java
index a48ae35..9f57768 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessContext.java
+++ b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessContext.java
@@ -1,4 +1,4 @@
-package com.databasir.core.infrastructure.oauth2;
+package com.databasir.core.domain.app.handler;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessResult.java b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessResult.java
similarity index 78%
rename from core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessResult.java
rename to core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessResult.java
index 550649c..a0a2eb6 100644
--- a/core/src/main/java/com/databasir/core/infrastructure/oauth2/OAuthProcessResult.java
+++ b/core/src/main/java/com/databasir/core/domain/app/handler/OAuthProcessResult.java
@@ -1,4 +1,4 @@
-package com.databasir.core.infrastructure.oauth2;
+package com.databasir.core.domain.app.handler;
 
 import lombok.Data;