Skip to content

Commit

Permalink
Merge pull request #56 from KCY-Fit-a-Pet/feat/40
Browse files Browse the repository at this point in the history
카카오 Oauth 구현 && 백엔드 연동
  • Loading branch information
psychology50 authored Jan 4, 2024
2 parents 22b399d + 46f371f commit 10a544c
Show file tree
Hide file tree
Showing 14 changed files with 389 additions and 67 deletions.
12 changes: 12 additions & 0 deletions fit-a-pet-client/fit-a-pet-client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
4A0750D22B07D44000281A4C /* UploadPetPhotoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0750D12B07D44000281A4C /* UploadPetPhotoVC.swift */; };
4A0750D42B0892B900281A4C /* CustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0750D32B0892B900281A4C /* CustomNavigationBar.swift */; };
4A0750D82B0D130F00281A4C /* PetRegistrationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0750D72B0D130F00281A4C /* PetRegistrationManager.swift */; };
4A0974282B45BFA8008B4E43 /* OauthCodeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0974272B45BFA8008B4E43 /* OauthCodeVC.swift */; };
4A0FEA492B1B5F6F0084CA6C /* FindInputPhoneNumVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0FEA482B1B5F6F0084CA6C /* FindInputPhoneNumVC.swift */; };
4A0FEA4B2B1B5F820084CA6C /* FindInputAuthNumVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0FEA4A2B1B5F820084CA6C /* FindInputAuthNumVC.swift */; };
4A15F2072AA641910098F2F7 /* CustomNextBtn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A15F2062AA641910098F2F7 /* CustomNextBtn.swift */; };
Expand Down Expand Up @@ -69,6 +70,7 @@
4A0750D12B07D44000281A4C /* UploadPetPhotoVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UploadPetPhotoVC.swift; sourceTree = "<group>"; };
4A0750D32B0892B900281A4C /* CustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationBar.swift; sourceTree = "<group>"; };
4A0750D72B0D130F00281A4C /* PetRegistrationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PetRegistrationManager.swift; sourceTree = "<group>"; };
4A0974272B45BFA8008B4E43 /* OauthCodeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OauthCodeVC.swift; sourceTree = "<group>"; };
4A0FEA482B1B5F6F0084CA6C /* FindInputPhoneNumVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindInputPhoneNumVC.swift; sourceTree = "<group>"; };
4A0FEA4A2B1B5F820084CA6C /* FindInputAuthNumVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindInputAuthNumVC.swift; sourceTree = "<group>"; };
4A15F2062AA641910098F2F7 /* CustomNextBtn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNextBtn.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -137,6 +139,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
4A0974262B45BF67008B4E43 /* OauthVC */ = {
isa = PBXGroup;
children = (
4A0974272B45BFA8008B4E43 /* OauthCodeVC.swift */,
);
path = OauthVC;
sourceTree = "<group>";
};
4A15F20C2AA8B3FB0098F2F7 /* SignUpVC */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -191,6 +201,7 @@
4ABE58582A85E8B400E22C5F /* ViewControllers */ = {
isa = PBXGroup;
children = (
4A0974262B45BF67008B4E43 /* OauthVC */,
4AF0C8572B2627BE00A45EEE /* EditUserVC */,
4ACDD49F2AD9B32400CD8F1A /* RegistPet */,
4ACDD49A2AD9A9F600CD8F1A /* FindAccountVC */,
Expand Down Expand Up @@ -489,6 +500,7 @@
4ACDD4A92ADAFFD100CD8F1A /* InputPetBirthVC.swift in Sources */,
4A15F2142AA8B4A50098F2F7 /* InputPwVC.swift in Sources */,
4AA999942A8485A500E495FA /* SceneDelegate.swift in Sources */,
4A0974282B45BFA8008B4E43 /* OauthCodeVC.swift in Sources */,
4AD354222AAF7E62004A47B3 /* TabBarController.swift in Sources */,
4A0FEA4B2B1B5F820084CA6C /* FindInputAuthNumVC.swift in Sources */,
4AF0C8522B24E0F000A45EEE /* TableViewModel.swift in Sources */,
Expand Down
Binary file not shown.
62 changes: 58 additions & 4 deletions fit-a-pet-client/fit-a-pet-client/API/AlamofireManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ class AlamofireManager {
.response { response in
switch response.result {
case .success(let data):
if let responseHeaders = response.response?.allHeaderFields as? [String: String],
let accessToken = responseHeaders["accessToken"] {
KeychainHelper.saveAccessToken(accessToken: accessToken)
os_log("sms token: %@", log: .default, type: .info, accessToken)
}
completion(.success(data))
case .failure(let error):
completion(.failure(error))
Expand Down Expand Up @@ -267,19 +272,68 @@ class AlamofireManager {
}
}

func kakaoCodeGet(completion: @escaping(Result<Data?, Error>) -> Void){
os_log("MyAlamofireManager - kakaoCodeGet() called ", log: .default, type: .info)
func oauthLogin(completion: @escaping(Result<Data?, Error>) -> Void){
os_log("MyAlamofireManager - oauthLogin() called", log: .default, type: .info)

self.session.request(MySearchRouter.oauthLogin)
.validate(statusCode: 200..<300)
.response { response in
switch response.result {
case .success(let data):
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}
}
func oauthSendSms(completion: @escaping(Result<Data?, Error>) -> Void){
os_log("MyAlamofireManager - oauthSendSms() called", log: .default, type: .info)

self.session.request(MySearchRouter.kakaoCode)
self.session.request(MySearchRouter.oauthSendSms)
.validate(statusCode: 200..<300)
.response { response in
switch response.result {
case .success(let data):
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}
}
}

func oauthCheckSms(_ code: String, completion: @escaping(Result<Data?, Error>) -> Void){
os_log("MyAlamofireManager - oauthCheckSms() called userInput: %@", log: .default, type: .info, code)

self.session.request(MySearchRouter.oauthCheckSms(code: code))
.validate(statusCode: 200..<300)
.response { response in
switch response.result {
case .success(let data):
if let responseHeaders = response.response?.allHeaderFields as? [String: String],
let accessToken = responseHeaders["accessToken"] {
KeychainHelper.saveAccessToken(accessToken: accessToken)
os_log("sms token: %@", log: .default, type: .info, accessToken)
}
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}
}

func oauthRegistUser(_ name: String, _ uid: String, completion: @escaping(Result<Data?, Error>) -> Void){
os_log("MyAlamofireManager - oauthCheckSms() called userInput: %@ ,, %@", log: .default, type: .info, name, uid)

self.session.request(MySearchRouter.oauthRegistUser(name: name, uid: uid))
.validate(statusCode: 200..<300)
.response { response in
switch response.result {
case .success(let data):
completion(.success(data))
case .failure(let error):
completion(.failure(error))
}
}
}
}

70 changes: 57 additions & 13 deletions fit-a-pet-client/fit-a-pet-client/API/MySearchRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,29 @@ enum MySearchRouter: URLRequestConvertible {
case findId(phone: String, code: String)
case findPw(phone: String, newPassword: String, code: String)
case existId(uid: String)
case userProfileInfo
case userProfileInfo, oauthLogin, oauthSendSms
case userNotifyType(type: String)
case editUserPw(type: String, prePassword: String, newPassword: String)
case editUserName(type: String, name: String)
case kakaoCode
case oauthCheckSms(code: String)
case oauthRegistUser(name: String, uid: String)

var baseURL: URL {
switch self {
case .presignedurl:
return URL(string: API.PRESIGNEDURL)!
case .uploadImage:
return URL(string: PAYLOADURL.PAYLOAD)!
case .kakaoCode:
return URL(string: "https://kauth.kakao.com/oauth/authorize")!
default:
return URL(string: API.BASE_URL)!
}
}

var method: HTTPMethod {
switch self {
case .sendSms, .checkSms, .login, .regist, .presignedurl, .registPet,.sendAuthSms, .checkAuthSms, .findId, .findPw:
case .sendSms, .checkSms, .login, .regist, .presignedurl, .registPet,.sendAuthSms, .checkAuthSms, .findId, .findPw, .oauthLogin, .oauthSendSms, .oauthCheckSms, .oauthRegistUser:
return .post
case .kakaoCode, .existId, .userProfileInfo, .userNotifyType:
case .existId, .userProfileInfo, .userNotifyType:
return .get
case .uploadImage, .editUserPw, .editUserName:
return .put
Expand All @@ -57,20 +56,26 @@ enum MySearchRouter: URLRequestConvertible {
return "auth/register"
case .presignedurl:
return "C7QXbC20ti"
case .uploadImage, .kakaoCode:
case .uploadImage:
return " "
case .registPet:
return "pets"
case .sendAuthSms, .checkAuthSms:
return "auth/search-sms"
case .oauthLogin:
return "auth/oauth"
case .oauthSendSms, .oauthCheckSms:
return "auth/oauth/\(OauthInfo.oauthId)/sms"
case .oauthRegistUser:
return "auth/oauth/\(OauthInfo.oauthId)"
case .findId, .findPw:
return "accounts/search"
case .existId:
return "accounts/exists"
case .userProfileInfo, .editUserPw, .editUserName:
return "accounts"
return "accounts/\(UserDefaults.standard.string(forKey: "id")!)"
case .userNotifyType:
return "accounts/notify"
return "accounts/\(UserDefaults.standard.string(forKey: "id")!)/notify"
}
}

Expand Down Expand Up @@ -103,8 +108,14 @@ enum MySearchRouter: URLRequestConvertible {
return ["type": type, "prePassword": prePassword, "newPassword": newPassword]
case let .editUserName(type, name):
return ["type": type, "name": name]
case .uploadImage(_), .kakaoCode, .userProfileInfo:
case .uploadImage(_), .userProfileInfo, .oauthLogin, .oauthSendSms:
return [:]
case let .oauthCheckSms(code):
return ["code": code]
case let .oauthRegistUser(name, uid):
return ["name": name, "uid": uid]
// case let .oauthLogin:
// return ["id": id, "nonce": nonce, "provider": provider]
}
}

Expand Down Expand Up @@ -225,18 +236,51 @@ enum MySearchRouter: URLRequestConvertible {
case .editUserName(let type, let name):
let bodyParameters = ["name": name]
let queryParameters = [URLQueryItem(name: "type", value: type)]
print(url)

if let accessToken = KeychainHelper.loadAccessToken() {
request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
} else {
request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)
}

case .oauthLogin:
let idToken = KeychainHelper.loadTempToken()!

let bodyParameters = ["id": OauthInfo.oauthId, "idToken": idToken, "nonce": OauthInfo.nonce] as [String : Any]
let queryParameters = [URLQueryItem(name: "provider", value: OauthInfo.provider)]

request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)

case .oauthSendSms:
let idToken = KeychainHelper.loadTempToken()!

let bodyParameters = ["to": OauthInfo.phoneNum, "idToken": idToken, "nonce": OauthInfo.nonce] as [String : Any]
let queryParameters = [URLQueryItem(name: "provider", value: OauthInfo.provider)]

request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)
case .oauthCheckSms(let code):
let idToken = KeychainHelper.loadTempToken()!

let bodyParameters = ["to": OauthInfo.phoneNum, "idToken": idToken, "nonce": OauthInfo.nonce] as [String : Any]
let queryParameters = [URLQueryItem(name: "provider", value: OauthInfo.provider), URLQueryItem(name: "code", value: code)]

request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)

case .kakaoCode:
let queryParameters = [URLQueryItem(name: "client_id", value: "bbe38742c0998fecfaaaaaef6856fc32"),URLQueryItem(name: "redirect_uri", value: "kakaobbe38742c0998fecfaaaaaef6856fc32://oauth"), URLQueryItem(name: "response_type", value: "code")]
case .oauthRegistUser(let name, let uid):
let idToken = KeychainHelper.loadTempToken()!

let bodyParameters = ["name": name, "uid": uid, "idToken": idToken, "nonce": OauthInfo.nonce] as [String : Any]
let queryParameters = [URLQueryItem(name: "provider", value: OauthInfo.provider)]

if let accessToken = KeychainHelper.loadAccessToken() {
request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
} else {
request = createURLRequestWithBodyAndQuery(url: url, bodyParameters: bodyParameters, queryParameters: queryParameters)
}

request = createURLRequestWithQuery(url: baseURL, queryParameters: queryParameters)

default:
request = createURLRequestWithBody(url: url)
Expand Down
8 changes: 7 additions & 1 deletion fit-a-pet-client/fit-a-pet-client/Utils/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Foundation

enum API{
static let BASE_URL : String = "http://www.fitapet.co.kr:8080/api/v1/"
static let BASE_URL : String = "https://fitapet.co.kr/api/v1/"
static let PRESIGNEDURL : String = "https://h1d5jjb17z.apigw.ntruss.com/obj/photo/"
}

Expand Down Expand Up @@ -36,3 +36,9 @@ enum FindIdPwSwitch{
static var userUid = ""
}

enum OauthInfo{
static var oauthId = 0
static var phoneNum = ""
static var nonce = ""
static var provider = ""
}
50 changes: 41 additions & 9 deletions fit-a-pet-client/fit-a-pet-client/Utils/KeyChainHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,36 +35,68 @@ class KeychainHelper {
}
}

static func savePassword(password: String) {
static func saveTempToken(tempToken: String) {
let passwordQuery: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: "password",
kSecValueData: password.data(using: .utf8)!,
kSecAttrAccount: "tempToken",
kSecValueData: tempToken.data(using: .utf8)!,
]

let status = SecItemAdd(passwordQuery as CFDictionary, nil)
if status == errSecDuplicateItem {
SecItemUpdate(passwordQuery as CFDictionary, [kSecValueData: password.data(using: .utf8)!] as CFDictionary)
SecItemUpdate(passwordQuery as CFDictionary, [kSecValueData: tempToken.data(using: .utf8)!] as CFDictionary)
} else if status != noErr {
print("Failed to save password to Keychain")
print("Failed to save tempToken to Keychain")
}
}

static func loadPassword() -> String? {
static func loadTempToken() -> String? {
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: "password",
kSecAttrAccount: "tempToken",
kSecReturnData: kCFBooleanTrue!,
]

var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)

if status == noErr, let data = item as? Data, let password = String(data: data, encoding: .utf8) {
return password
if status == noErr, let data = item as? Data, let token = String(data: data, encoding: .utf8) {
return token
} else {
return nil
}
}

// static func savePassword(password: String) {
// let passwordQuery: [CFString: Any] = [
// kSecClass: kSecClassGenericPassword,
// kSecAttrAccount: "password",
// kSecValueData: password.data(using: .utf8)!,
// ]
//
// let status = SecItemAdd(passwordQuery as CFDictionary, nil)
// if status == errSecDuplicateItem {
// SecItemUpdate(passwordQuery as CFDictionary, [kSecValueData: password.data(using: .utf8)!] as CFDictionary)
// } else if status != noErr {
// print("Failed to save password to Keychain")
// }
// }
//
// static func loadPassword() -> String? {
// let query: [CFString: Any] = [
// kSecClass: kSecClassGenericPassword,
// kSecAttrAccount: "password",
// kSecReturnData: kCFBooleanTrue!,
// ]
//
// var item: CFTypeRef?
// let status = SecItemCopyMatching(query as CFDictionary, &item)
//
// if status == noErr, let data = item as? Data, let password = String(data: data, encoding: .utf8) {
// return password
// } else {
// return nil
// }
// }
}

9 changes: 5 additions & 4 deletions fit-a-pet-client/fit-a-pet-client/Utils/ResponseData.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
struct ResponseData: Decodable {
let status: String
let message: String
}

//struct ResponseData: Decodable {
// let status: String
// let message: String
//}
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,13 @@ class FindInputAuthNumVC: CustomNavigationBar{
}

@objc func changeFindIdCheckVC(_ sender: UIButton){
let nextVC = ResetPwVC(title: FindIdPwSwitch.findAuth)

var nextVC: UIViewController

if FindIdPwSwitch.findAuth == "아이디 찾기"{
let nextVC = FindIdCheckVC(title: FindIdPwSwitch.findAuth)
nextVC = FindIdCheckVC(title: FindIdPwSwitch.findAuth)
}else{
nextVC = ResetPwVC(title: FindIdPwSwitch.findAuth)
}

AlamofireManager.shared.checkAuthSms(FindIdPwSwitch.phoneNum, FindIdPwSwitch.code){
Expand Down
Loading

0 comments on commit 10a544c

Please sign in to comment.