Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/actions/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func App() *buffalo.App {

auth := app.Group(apiPath + "/auth")
auth.Middleware.Skip(mciammanager.TokenValidMiddleware, AuthMCIAMLogin, AuthMCIAMLoginRefresh)
auth.Middleware.Skip(mciammanager.SetContextMiddleware, AuthMCIAMLogin)
auth.Middleware.Skip(mciammanager.SetContextMiddleware, AuthMCIAMLogin, AuthMCIAMLoginRefresh)
auth.POST("/login", AuthMCIAMLogin)
auth.POST("/refresh", AuthMCIAMLoginRefresh)
auth.POST("/validate", AuthMCIAMValidate)
Expand Down
69 changes: 58 additions & 11 deletions api/actions/auth.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package actions

import (
"log"
"mc_web_console_api/handler"
"mc_web_console_api/handler/self"
"mc_web_console_api/models"
"net/http"

"log"

"github.com/gobuffalo/buffalo"
"github.com/gobuffalo/pop/v6"
)
Expand Down Expand Up @@ -49,6 +48,7 @@ func AuthLogin(c buffalo.Context) error {
}

func AuthLoginRefresh(c buffalo.Context) error {

tx := c.Value("tx").(*pop.Connection)
userId := c.Value("UserId").(string)
sess, err := self.GetUserByUserId(tx, userId)
Expand Down Expand Up @@ -131,31 +131,78 @@ func AuthMCIAMLogin(c buffalo.Context) error {

func AuthMCIAMLoginRefresh(c buffalo.Context) error {
commonRequest := &handler.CommonRequest{}
c.Bind(commonRequest)
if err := c.Bind(commonRequest); err != nil {
return c.Render(http.StatusBadRequest, r.JSON(map[string]interface{}{"error": "Binding error: " + err.Error()}))
}

if commonRequest.Request == nil {
return c.Render(http.StatusBadRequest, r.JSON(map[string]interface{}{"error": "Request data is missing"}))
}

requestData, ok := commonRequest.Request.(map[string]interface{})
if !ok {
return c.Render(http.StatusBadRequest, r.JSON(map[string]interface{}{"error": "Invalid request format"}))
}

_, hasRefreshToken := requestData["refresh_token"]
if !hasRefreshToken {
return c.Render(http.StatusBadRequest, r.JSON(map[string]interface{}{"error": "refresh_token is required"}))
}

tx := c.Value("tx").(*pop.Connection)

var refreshRes *handler.CommonResponse
var err error

if commonRequest.Request != nil {
refreshRes, _ = handler.AnyCaller(c, "loginrefresh", commonRequest, true)
refreshRes, err = handler.AnyCaller(c, "loginrefresh", commonRequest, false)

if err != nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": "AnyCaller error: " + err.Error()}))
}
} else {
sess, err := self.GetUserByUserId(tx, c.Value("UserId").(string))
userId := c.Value("UserId")
if userId == nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": "UserId not found in context"}))
}

sess, err := self.GetUserByUserId(tx, userId.(string))
if err != nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": err.Error()}))
}

commonRequest.Request = map[string]interface{}{"refresh_token": sess.RefreshToken}
refreshRes, _ = handler.AnyCaller(c, "loginrefresh", commonRequest, true)

refreshRes, err = handler.AnyCaller(c, "loginrefresh", commonRequest, false)

if err != nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": "AnyCaller error: " + err.Error()}))
}
}

if refreshRes == nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": "Response is nil from AnyCaller"}))
}

if refreshRes.Status.StatusCode != 200 {
return c.Render(refreshRes.Status.StatusCode, r.JSON(map[string]interface{}{"error": refreshRes.Status.Message}))
errorResponse := &handler.CommonResponse{
ResponseData: refreshRes.ResponseData,
Status: handler.WebStatus{
StatusCode: refreshRes.Status.StatusCode,
Message: refreshRes.Status.Message,
},
}

return c.Render(refreshRes.Status.StatusCode, r.JSON(errorResponse))
}

_, err := self.UpdateUserSesssFromResponseData(tx, refreshRes, c.Value("UserId").(string))
if err != nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": err.Error()}))
if refreshRes.ResponseData == nil {
return c.Render(http.StatusInternalServerError, r.JSON(map[string]interface{}{"error": "ResponseData is nil from AnyCaller"}))
}

return c.Render(refreshRes.Status.StatusCode, r.JSON(refreshRes))
commonResponse := handler.CommonResponseStatusOK(refreshRes.ResponseData)

return c.Render(commonResponse.Status.StatusCode, r.JSON(commonResponse))
}

func AuthMCIAMLogout(c buffalo.Context) error {
Expand Down
17 changes: 15 additions & 2 deletions api/handler/mciammanager/middleware.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package mciammanager

import (
"fmt"
"log"
"mc_web_console_api/handler"
"net/http"
Expand Down Expand Up @@ -39,19 +38,33 @@ func getCertsEndpoint() string {
}
baseUrl := viper.Get("services.mc-iam-manager.baseurl").(string)
certUri := viper.Get("serviceActions.mc-iam-manager.Getcerts.resourcePath").(string)
fmt.Println("Cert Endpoint is : ", baseUrl+certUri)
return baseUrl + certUri
}

func TokenValidMiddleware(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
accessToken := strings.TrimPrefix(c.Request().Header.Get("Authorization"), "Bearer ")

// 토큰이 비어있는지 확인
if accessToken == "" {
return c.Render(http.StatusUnauthorized, render.JSON(map[string]interface{}{"error": "Access token is missing"}))
}

// JWT 토큰 형식 기본 검증 (3개 부분으로 구성)
parts := strings.Split(accessToken, ".")
if len(parts) != 3 {
return c.Render(http.StatusUnauthorized, render.JSON(map[string]interface{}{"error": "Invalid token format"}))
}

err := iamtokenvalidator.IsTokenValid(accessToken)
if err != nil {
if strings.Contains(err.Error(), "token signature is invalid") {
return c.Render(http.StatusForbidden, render.JSON(map[string]interface{}{"error": err.Error()}))
} else if strings.Contains(err.Error(), "token is expired") {
return c.Render(http.StatusUnauthorized, render.JSON(map[string]interface{}{"error": err.Error()}))
} else if strings.Contains(err.Error(), "token contains an invalid number of segments") {
log.Printf("Malformed token: %s", err.Error())
return c.Render(http.StatusUnauthorized, render.JSON(map[string]interface{}{"error": "Invalid token format"}))
}
log.Println(err.Error())
return c.Render(http.StatusInternalServerError, render.JSON(map[string]interface{}{"error": err.Error()}))
Expand Down
2 changes: 1 addition & 1 deletion front/actions/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func App() *buffalo.App {
authapi := app.Group("/api")
authapi.Middleware.Skip(middleware.IsTokenExistMiddleware, SessionInitializer)
authapi.POST("/auth/login", SessionInitializer)

authapi.POST("/auth/refresh", SessionInitializer)
app.Redirect(http.StatusSeeOther, "/", RootPathForRedirectString) //home redirect to dash

pages := app.Group("/webconsole")
Expand Down
15 changes: 13 additions & 2 deletions front/actions/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ func SessionInitializer(c buffalo.Context) error {
if err != nil {
return c.Render(http.StatusInternalServerError, defaultRender.JSON(map[string]interface{}{"error": err.Error()}))
}

// Authorization 헤더 추가
if authHeader := c.Request().Header.Get("Authorization"); authHeader != "" {
req.Header.Set("Authorization", authHeader)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
Expand All @@ -38,9 +43,15 @@ func SessionInitializer(c buffalo.Context) error {
return c.Render(resp.StatusCode, defaultRender.JSON(map[string]interface{}{"message": errmsg}))
}

accessToken := data["responseData"].(map[string]interface{})["access_token"]
// access_token과 refresh_token을 각각 추출
responseDataMap := data["responseData"].(map[string]interface{})
accessToken := responseDataMap["access_token"].(string)
refreshToken := responseDataMap["refresh_token"].(string)

return c.Render(http.StatusOK, defaultRender.JSON(map[string]interface{}{"access_token": accessToken}))
return c.Render(http.StatusOK, defaultRender.JSON(map[string]interface{}{
"access_token": accessToken,
"refresh_token": refreshToken,
}))
}

func UserLogin(c buffalo.Context) error {
Expand Down
63 changes: 41 additions & 22 deletions front/assets/js/common/api/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,35 @@ export async function commonAPIPost(url, data, attempt) {
if (!attempt || attempt === undefined) {
if (error.response) {
const status = error.response.status;

switch (status) {
case 400:
alert("Bad Request: " + error.message);
return error;
case 401:
console.log("status is 401", status)
console.log("Attempting token refresh...")
// Authentication failed - try token refresh
const authrefreshStatus = await webconsolejs["common/cookie/authcookie"].refreshCookieAccessToken();
if (authrefreshStatus) {
console.log("refreshCookieAccessToken success. Retrying request with refreshed token...");
return commonAPIPost(url, data, true);
} else {
alert("Session is expired");
try {
const authrefreshStatus = await webconsolejs["common/cookie/authcookie"].refreshCookieAccessToken();
console.log("authrefreshStatus", authrefreshStatus)
if (authrefreshStatus) {
console.log("refreshCookieAccessToken success. Retrying request with refreshed token...");
return commonAPIPost(url, data, true);
} else {
console.error("Token refresh failed");
alert("Session is expired. Please login again.");
// 쿠키 정리
document.cookie = "Authorization=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "RefreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
window.location = "/auth/login";
return;
}
} catch (refreshError) {
console.error("Error during token refresh:", refreshError);
alert("Failed to refresh session. Please login again.");
// 쿠키 정리
document.cookie = "Authorization=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
document.cookie = "RefreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
window.location = "/auth/login";
return;
}
Expand Down Expand Up @@ -68,28 +84,31 @@ export async function commonAPIPost(url, data, attempt) {
}
}

export async function commonAPIPostWithoutRetry(url, data) {
console.log("#### commonAPIPost", );
console.log("Request URL :", url);
console.log("Request Data :", JSON.stringify(data));
console.log("-----------------------");
export async function commonAPIPostWithoutRetry(url, data) {
try {
if( data === undefined) {
var response = await axios.post(url);
}else {
var response = await axios.post(url, data);
let response;
if (data === undefined) {
response = await axios.post(url);
} else {
response = await axios.post(url, data);
}
console.log("#### commonAPIPost Response");
console.log("#### commonAPIPostWithoutRetry Response");
console.log("Response status : ", response.status);
console.log("Response : ", response.data);
console.log("Response from : ",url, response.data);
console.log("----------------------------");
return response;
} catch (error) {
console.log("#### commonAPIPost Error");
console.log("Error: ", error.response ? error.response.status : error.message);
console.log("#### commonAPIPostWithoutRetry Error");
console.log("Error status:", error.response ? error.response.status : "No response");
console.log("Error message:", error.message);
console.log("Error response data:", error.response ? error.response.data : "No response data");
if (error.response && error.response.data) {
if (typeof error.response.data === 'object') {
console.log("Error response data keys:", Object.keys(error.response.data));
}
}
console.log("----------------------------");
console.log("Request failed :", error);
return error
return error;
}
}

Expand Down
Loading
Loading