// // HPAuthFlow.m // HotPocket (macOS) // // Created by Tomek Wójcik on 21/09/2025. // #import "HPAuthFlow.h" #import "HPAPI.h" #import "HPCredentialsHelper.h" #import "HPRPCClient.h" #import "NSBundle+HotPocketExtensions.h" #import "NSURL+HotPocketExtensions.h" @implementation HPAuthParams #pragma mark - HPAuthParams implementation @end @implementation HPAuthFlow (HPAuthFlowPrivate) #pragma mark - HPAuthFlow private interface -(NSURL *)resolveAuthenticateURL { if (self.baseURL == nil) { return nil; } if (self.baseURL.isUsableInHotPocket == NO) { return nil; } NSBundle *mainBundle = [NSBundle mainBundle]; NSURLComponents *authURLComponents = [NSURLComponents componentsWithURL:self.baseURL resolvingAgainstBaseURL:NO]; authURLComponents.path = @"/integrations/extension/authenticate/"; authURLComponents.queryItems = @[ [NSURLQueryItem queryItemWithName:@"source" value:[[mainBundle infoDictionary] valueForKey:@"HPAuthFlowSource"]], [NSURLQueryItem queryItemWithName:@"session_token" value:self.sessionToken], ]; return authURLComponents.URL; } @end @implementation HPAuthFlow #pragma mark - Initialization -(id)init { if (self = [super init]) { self.baseURL = nil; self.sessionToken = nil; } return self; } #pragma mark - Public interface -(NSURL *)start { if (self.baseURL == nil) { return nil; } if (self.sessionToken == nil) { self.sessionToken = [[NSUUID UUID] UUIDString]; } return [self resolveAuthenticateURL]; } -(HPAuthParams *)handlePostAuthenticateURL:(NSURL *)url { if (url == nil) { return nil; } NSString *expectedScheme = [NSBundle postAuthenticateURLScheme]; NSString *expectedHost = [NSBundle postAuthenticateURLHost]; if (expectedScheme == nil || expectedHost == nil) { return nil; } NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; if ([urlComponents.scheme isEqualToString:expectedScheme] == NO) { return nil; } if ([urlComponents.host isEqualToString:expectedHost] == NO) { return nil; } HPAuthParams *result = [[HPAuthParams alloc] init]; for (NSURLQueryItem *queryItem in urlComponents.queryItems) { if ([queryItem.name isEqualToString:@"auth_key"] == YES) { result.authKey = queryItem.value; } else if ([queryItem.name isEqualToString:@"session_token"] == YES) { result.sessionToken = queryItem.value; } } if ([self.sessionToken isEqualToString:result.sessionToken] == NO) { return nil; } return result; } -(BOOL)handleAuthParams:(HPAuthParams *)authParams { [[NSNotificationCenter defaultCenter] postNotificationName:@"AuthFlowDidReceiveAuthParams" object:self]; HPRPCClient *rpcClient = [[HPRPCClient alloc] initWithBaseURL:self.baseURL accessToken:nil]; NSArray *callParams = @[ authParams.authKey, [HPAPI getAccessTokenMeta], ]; BOOL callResult = [rpcClient call:self.sessionToken method:@"accounts.access_tokens.create" params:callParams endopoint:@"/accounts/rpc/" completionHandler:^(NSString *callId, HPRPCCallResult *result) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if (result.error != nil) { NSLog(@"-[HPAuthFlow handleAuthParams:] error=`%@`", result.error); } else { HPCredentialsHelper *credentialsHelper = [HPCredentialsHelper sharedHelper]; [credentialsHelper saveCredentials:[self.baseURL absoluteString] accessToken:(NSString *)result.result]; } self.sessionToken = nil; [[NSNotificationCenter defaultCenter] postNotificationName:@"AuthFlowDidFinish" object:self]; }); }]; return callResult; } @end