2015-04-20 18 views
12

Wir versuchen, Client-SSL-Zertifikate für die Benutzerauthentifizierung in einer Unternehmens-iOS-App zu verwenden.Verwenden des Client-SSL-Zertifikats von .mobileconfig in der Enterprise iOS-App

  • Wir können den Client SSL-Zertifikat auf dem Server generieren
  • Der Benutzer dies durch eine .mobileconfig installieren können
  • Authentifizierung auf einen Webserver in Safari arbeitet mit der installierten cert.
  • Eine HTTP-Anfrage in einer iOS-App kann nicht ausgeführt werden (das Zertifikat wird nicht verwendet).

Wie schaffen wir das? Vielen Dank!

+0

Erhalten Sie Ihre Websites und Dienste mit selbst signierten Zertifikat für https Sicherung? Oder versuchen Sie, das Zertifikat als Mittel zur Authentifizierung zu verwenden, anstatt Benutzernamen und Passwort zu verwenden? –

+1

Wir möchten das Zertifikat verwenden, um den Benutzer zu authentifizieren (anstelle von Benutzername/Passwort). –

+0

Welche Lösung verwenden Sie für Ihre Webanwendungen NTLM oder Kerberos-Authentifizierung? –

Antwort

8

Übersicht:

Sie das Client-SSL-Zertifikat auf dem Gerät Schlüsselbund installiert hat.

Safari.app und Mail.app können auf diesen Schlüsselbund zugreifen, die iOS-App dagegen nicht.

Der Grund ist, dass die Apps, die wir entwickeln, Sandboxed sind und keine Zugriffsrechte außerhalb davon im nicht-jailbroken Gerät haben.

Da Safari Zugriff darauf hat, hatte es keine Probleme, sich mit der Serverherausforderung zu verbinden und zu authentifizieren.

Lösung:

Fügen Sie die exportierte P12-Datei mit dem App-Bundle und beziehen sich auf das richtige Client-Zertifikat finden der Server war auf der Suche for.It ist eigentlich eine Abhilfe. Die Hardcoding ist der zuverlässige Weg, um die P12-Datei zu greifen.

Implementation:

betreffende Verfahren ist in willSendRequestForAuthenticationChallengeNSURLConenction delegate. Sie müssen den Challenge-Typ NSURLAuthenticationMethodClientCertificate berücksichtigen, um die Serverherausforderung zu bewältigen. Hier haben wir die Magie implementiert, um die korrekte Zertifikatsidentität aus der eingebetteten P12-Datei zu extrahieren. Code ist unter

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    if ([challenge previousFailureCount] > 0) { 
     //this will cause an authentication failure 
      [[challenge sender] cancelAuthenticationChallenge:challenge]; 
       NSLog(@"Bad Username Or Password");        
     return; 
    } 



    //this is checking the server certificate 
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
            SecTrustResultType result; 
            //This takes the serverTrust object and checkes it against your keychain 
            SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result); 

      //if we want to ignore invalid server for certificates, we just accept the server 
            if (kSPAllowInvalidServerCertificates) { 
                [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge]; 
       return; 
            } else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm ||  result == kSecTrustResultUnspecified) { 
       //When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server 
                [challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge]; 
       return; 
            } 
        } else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) { 
       //this handles authenticating the client certificate 

     /* 
What we need to do here is get the certificate and an an identity so we can do this: 
    NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:myCerts persistence:NSURLCredentialPersistencePermanent]; 
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 

    It's easy to load the certificate using the code in -installCertificate 
    It's more difficult to get the identity. 
    We can get it from a .p12 file, but you need a passphrase: 
    */ 

    NSString *p12Path = [[BundleManager bundleForCurrentSkin] pathForResource:kP12FileName ofType:@"p12"]; 
    NSData *p12Data = [[NSData alloc] initWithContentsOfFile:p12Path]; 

    CFStringRef password = CFSTR("PASSWORD"); 
    const void *keys[] = { kSecImportExportPassphrase }; 
    const void *values[] = { password }; 
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 
    CFArrayRef p12Items; 

    OSStatus result = SecPKCS12Import((CFDataRef)p12Data, optionsDictionary, &p12Items); 

    if(result == noErr) { 
             CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0); 
             SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity); 

             SecCertificateRef certRef; 
             SecIdentityCopyCertificate(identityApp, &certRef); 

             SecCertificateRef certArray[1] = { certRef }; 
             CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL); 
             CFRelease(certRef); 

             NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent]; 
             CFRelease(myCerts); 

             [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
         } 
    } else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) { 
    // For normal authentication based on username and password. This could be NTLM or Default. 

     DAVCredentials *cred = _parentSession.credentials; 
        NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession]; 
    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
    } else { 
     //If everything fails, we cancel the challenge. 
     [[challenge sender] cancelAuthenticationChallenge:challenge]; 
    } 
} 

Referenz: Ref1, Ref2, Ref3

hoffte, das hilft

+0

@Christopher Stott - Versuchen Sie es und lassen Sie es mich wissen.Wenn Sie immer noch das Problem haben, fühlen Sie sich frei zu kommentieren. –

+0

Ich habe woanders gelesen, dass es private Methoden gibt, um auf Gerätezertifikate zuzugreifen.Da ich eine über einen Unternehmensspeicher verteilte App erstelle, interessiert mich die App Store-Zurückweisung nicht. –