2015-04-20 12 views
12

Stiamo provando a utilizzare i certificati SSL client per l'autenticazione utente in un'app iOS aziendale.Utilizzo del certificato SSL client da .mobileconfig all'interno dell'app Enterprise iOS

  • Possiamo generare il CERT client SSL sul server
  • L'utente può installare questo attraverso un .mobileconfig
  • autenticazione a un server web in Safari funziona con il CERT installato.
  • Effettuare una richiesta http dall'interno di un'app iOS non riesce (il certificato non viene utilizzato).

Come possiamo farlo funzionare? Grazie!

+0

State salvaguardando i vostri siti web e servizi utilizzando certificato auto firmato per https? o Stai cercando di utilizzare il certificato come mezzo per l'autenticazione invece di utilizzare nome utente e password? –

+1

Vogliamo utilizzare il certificato per autenticare l'utente (invece di usare nome utente/password). –

+0

Qual è la soluzione esistente che si utilizza per l'autenticazione NTLM o Kerberos delle app Web? –

risposta

8

Panoramica:

È stato installato il certificato SSL client sul portachiavi dispositivo.

Safari.app e Mail.app hanno accesso a questo portachiavi mentre l'app iOS no.

La ragione è che le app che sviluppiamo sono in modalità sandbox e non dispongono di diritti di accesso al di fuori di esso nel dispositivo non jailbroken.

Come safari ha accesso ad esso, non ha avuto problemi di connessione e autenticazione contro la sfida del server.

Soluzione:

Includere il file esportato P12 con il fascio App e si riferiscono ad esso per trovare il certificato client corretto il server era alla ricerca for.It è in realtà una soluzione. L'hardcoding è il modo affidabile per prendere il file P12.

Implementazione:

metodo in questione è willSendRequestForAuthenticationChallenge in NSURLConenction delegate. È necessario considerare il tipo di sfida NSURLAuthenticationMethodClientCertificate per gestire la sfida del server. È qui che abbiamo implementato la magia per estrarre l'identità del certificato corretta dal file P12 incorporato. Codice è al di sotto

- (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]; 
    } 
} 

Riferimento: Ref1, Ref2, Ref3

Spero che questo aiuti

+0

@Christopher Stott - Prova questo e fammi sapere.Se hai ancora il problema, sentiti libero di commentare. –

+0

Ho letto da qualche altra parte che esistono metodi privati ​​per accedere ai certificati dei dispositivi.Dato che sto costruendo un'app distribuita tramite un negozio aziendale, non mi interessa il rifiuto di App Store. –

Problemi correlati