Skip to content

Commit

Permalink
Refactored methods to pass an accessGroup param needed for iOS Keycha…
Browse files Browse the repository at this point in the history
…in sharing
  • Loading branch information
maxperry committed Feb 7, 2017
1 parent 7119425 commit cb37815
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 23 deletions.
60 changes: 46 additions & 14 deletions RNKeychainManager/RNKeychainManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,28 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)
return reject(codeForError(error), messageForError(error), nil);
}

RCT_EXPORT_METHOD(setGenericPasswordForService:(NSString*)service withUsername:(NSString*)username withPassword:(NSString*)password resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(setGenericPasswordForService:(NSString*)service withAccessGroup:(NSString *)accessGroup withUsername:(NSString*)username withPassword:(NSString*)password resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
if(service == nil) {
service = [[NSBundle mainBundle] bundleIdentifier];
}

// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Remove any old values from the keychain
OSStatus osStatus = SecItemDelete((__bridge CFDictionaryRef) dict);

// Create dictionary of parameters to add
NSData* passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, passwordData, kSecValueData, username, kSecAttrAccount, nil];
dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, passwordData, kSecValueData, username, kSecAttrAccount, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Try to save to keychain
osStatus = SecItemAdd((__bridge CFDictionaryRef) dict, NULL);
Expand All @@ -102,13 +110,17 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)

}

RCT_EXPORT_METHOD(getGenericPasswordForService:(NSString*)service resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(getGenericPasswordForService:(NSString*)service withAccessGroup:(NSString *)accessGroup resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
if(service == nil) {
service = [[NSBundle mainBundle] bundleIdentifier];
}

// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Look up server in the keychain
NSDictionary* found = nil;
Expand Down Expand Up @@ -137,13 +149,17 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)

}

RCT_EXPORT_METHOD(resetGenericPasswordForService:(NSString*)service resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(resetGenericPasswordForService:(NSString*)service withAccessGroup:(NSString *)accessGroup resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
if(service == nil) {
service = [[NSBundle mainBundle] bundleIdentifier];
}

// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassGenericPassword), kSecClass, service, kSecAttrService, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Remove any old values from the keychain
OSStatus osStatus = SecItemDelete((__bridge CFDictionaryRef) dict);
Expand All @@ -156,16 +172,24 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)

}

RCT_EXPORT_METHOD(setInternetCredentialsForServer:(NSString*)server withUsername:(NSString*)username withPassword:(NSString*)password resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(setInternetCredentialsForServer:(NSString*)server withAccessGroup:(NSString *)accessGroup withUsername:(NSString*)username withPassword:(NSString*)password resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Remove any old values from the keychain
OSStatus osStatus = SecItemDelete((__bridge CFDictionaryRef) dict);

// Create dictionary of parameters to add
NSData* passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, passwordData, kSecValueData, username, kSecAttrAccount, nil];
dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, passwordData, kSecValueData, username, kSecAttrAccount, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Try to save to keychain
osStatus = SecItemAdd((__bridge CFDictionaryRef) dict, NULL);
Expand All @@ -178,10 +202,14 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)
return resolve(@(YES));
}

RCT_EXPORT_METHOD(getInternetCredentialsForServer:(NSString*)server resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(getInternetCredentialsForServer:(NSString*)server withAccessGroup:(NSString *)accessGroup resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){

// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Look up server in the keychain
NSDictionary* found = nil;
Expand Down Expand Up @@ -210,10 +238,14 @@ void rejectWithError(RCTPromiseRejectBlock reject, NSError *error)

}

RCT_EXPORT_METHOD(resetInternetCredentialsForServer:(NSString*)server resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
RCT_EXPORT_METHOD(resetInternetCredentialsForServer:(NSString*)server withAccessGroup:(NSString *)accessGroup resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){

// Create dictionary of search parameters
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:(__bridge id)(kSecClassInternetPassword), kSecClass, server, kSecAttrServer, kCFBooleanTrue, kSecReturnAttributes, kCFBooleanTrue, kSecReturnData, nil];

if (accessGroup) {
[dict setObject:accessGroup forKey:kSecAttrAccessGroup];
}

// Remove any old values from the keychain
OSStatus osStatus = SecItemDelete((__bridge CFDictionaryRef) dict);
Expand Down
12 changes: 3 additions & 9 deletions index.js → index.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,7 @@ export function resetGenericPassword(
* `false` if denied and throws an error if not supported on platform or there's no shared credentials
*/
export function requestSharedWebCredentials() : Promise {
if (Platform.OS !== 'ios') {
return Promise.reject(new Error(`requestSharedWebCredentials() is not supported on ${Platform.OS} yet`));
}
return RNKeychainManager.requestSharedWebCredentials();
return Promise.reject(new Error(`requestSharedWebCredentials() is not supported on ${Platform.OS} yet`));
}

/**
Expand All @@ -99,8 +96,5 @@ export function setSharedWebCredentials(
username: string,
password: string
) : Promise {
if (Platform.OS !== 'ios') {
return Promise.reject(new Error(`setSharedWebCredentials() is not supported on ${Platform.OS} yet`));
}
return RNKeychainManager.setSharedWebCredentialsForServer(server, username, password);
}
return Promise.reject(new Error(`setSharedWebCredentials() is not supported on ${Platform.OS} yet`));
}
112 changes: 112 additions & 0 deletions index.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { NativeModules, Platform } from 'react-native';
const { RNKeychainManager } = NativeModules;

/**
* Saves the `username` and `password` combination for `server`.
* @param {string} server URL to server.
* @param {string} accessGroup Group name for keychain sharing.
* @param {string} username Associated username or e-mail to be saved.
* @param {string} password Associated password to be saved.
* @return {Promise} Resolves to `true` when successful
*/
export function setInternetCredentials(
server: string,
username: string,
password: string,
accessGroup?: string
): Promise {
return RNKeychainManager.setInternetCredentialsForServer(server, accessGroup, username, password);
}

/**
* Fetches login combination for `server`.
* @param {string} server URL to server.
* @param {string} accessGroup Group name for keychain sharing.
* @return {Promise} Resolves to `{ server, username, password }` when successful
*/
export function getInternetCredentials(
server: string,
accessGroup?: string
): Promise {
return RNKeychainManager.getInternetCredentialsForServer(server, accessGroup);
}

/**
* Deletes all internet password keychain entries for `server`.
* @param {string} server URL to server.
* @param {string} accessGroup Group name for keychain sharing.
* @return {Promise} Resolves to `true` when successful
*/
export function resetInternetCredentials(
server: string,
accessGroup?: string
): Promise {
return RNKeychainManager.resetInternetCredentialsForServer(server, accessGroup);
}

/**
* Saves the `username` and `password` combination for `service`.
* @param {string} username Associated username or e-mail to be saved.
* @param {string} password Associated password to be saved.
* @param {string} service Reverse domain name qualifier for the service, defaults to `bundleId`.
* @param {string} accessGroup Group name for keychain sharing.
* @return {Promise} Resolves to `true` when successful
*/
export function setGenericPassword(
username: string,
password: string,
service?: string,
accessGroup?: string
): Promise {
return RNKeychainManager.setGenericPasswordForService(service, accessGroup, username, password);
}

/**
* Fetches login combination for `service`.
* @param {string} service Reverse domain name qualifier for the service, defaults to `bundleId`.
* @param {string} accessGroup Group name for keychain sharing.
* @return {Promise} Resolves to `{ service, username, password }` when successful
*/
export function getGenericPassword(
service?: string,
accessGroup?: string
): Promise {
return RNKeychainManager.getGenericPasswordForService(service, accessGroup);
}

/**
* Deletes all generic password keychain entries for `service`.
* @param {string} service Reverse domain name qualifier for the service, defaults to `bundleId`.
* @param {string} accessGroup Group name for keychain sharing.
* @return {Promise} Resolves to `true` when successful
*/
export function resetGenericPassword(
service?: string,
accessGroup?: string
): Promise {
return RNKeychainManager.resetGenericPasswordForService(service, accessGroup);
}

/**
* Asks the user for a shared web credential.
* @return {Promise} Resolves to `{ server, username, password }` if approved and
* `false` if denied and throws an error if not supported on platform or there's no shared credentials
*/
export function requestSharedWebCredentials() : Promise {
return RNKeychainManager.requestSharedWebCredentials();
}

/**
* Sets a shared web credential.
* @param {string} server URL to server.
* @param {string} username Associated username or e-mail to be saved.
* @param {string} password Associated password to be saved.
* @return {Promise} Resolves to `true` when successful
*/
export function setSharedWebCredentials(
server: string,
username: string,
password: string
) : Promise {
return RNKeychainManager.setSharedWebCredentialsForServer(server, username, password);
}

0 comments on commit cb37815

Please sign in to comment.