115

I am running into an issue while doing API calls to my apps backend, every connection now prompts with

CredStore - performQuery - Error copying matching creds.  Error=-25300, query={
    atyp = http;
    class = inet;
    "m_Limit" = "m_LimitAll";
    ptcl = http;
    "r_Attributes" = 1;
    srvr = "myappsurl.com";
    sync = syna;
}

I am a little lost as I am not sure what is causing this, or what CredStore even does. What purpose does CredStore serve in iOS?

Daniel Storm
  • 15,870
  • 6
  • 74
  • 133
Anthony Taylor
  • 2,340
  • 3
  • 19
  • 29

14 Answers14

38

This error occurs when trying to retrieve an URLCredential from URLCredentialStorage for an unknown URLProtectionSpace. e.g.

let protectionSpace = URLProtectionSpace.init(host: host, 
                                              port: port, 
                                              protocol: "http", 
                                              realm: nil, 
                                              authenticationMethod: nil)

var credential: URLCredential? = URLCredentialStorage.shared.defaultCredential(for: protectionSpace)

produces

CredStore - performQuery - Error copying matching creds.  Error=-25300, query={
    class = inet;
    "m_Limit" = "m_LimitAll";
    ptcl = http;
    "r_Attributes" = 1;
    srvr = host;
    sync = syna;
}

Give it a credential for the protection space:

let userCredential = URLCredential(user: user, 
                                   password: password, 
                                   persistence: .permanent)

URLCredentialStorage.shared.setDefaultCredential(userCredential, for: protectionSpace)

and the error goes away next time you try to retrieve the credential.

I am a little lost as I am not sure what is causing this, or what CredStore even does. What purpose does CredStore serve in iOS?

Credential storage on iOS allows users to securely store certificate-based or password-based credentials on the device either temporarily or permanently to the keychain.

I suspect that you have some sort of authentication on your backend server and that server is requesting an authentication challenge to your app (for which no credential exists).

It can probably be safely ignored as returning nil from the URLCredentialStorage is a valid response

Brett
  • 2,507
  • 20
  • 33
  • 2
    How would you go about created a protection space? – Tom Fox Jan 24 '18 at 18:11
  • @Brett can you please provide information for protectionSpace? – Pavlos Jan 30 '18 at 09:08
  • @Brett my fault just thought the first part was producing the error I have. after editing the Answer I can upvote it – Pavlos Jan 30 '18 at 10:30
  • 2
    how to use in Moya and Alamofire? – sony May 15 '18 at 03:58
  • 1
    I also have this issue when using alamofire https://stackoverflow.com/questions/50342214/how-to-upload-an-image-using-alamofire-with-basic-authentication , i don't know where to put userCredential in Alamofire :( – Alexa289 May 15 '18 at 04:44
  • 1
    @Brett, I am also facing this issue when calling Twilio API through AFNetwrking. Any suggestions, what to search in order to grab the issue with AFNetworking? – Sunita Dec 31 '18 at 06:45
12

I'm not sure why do we get this error when perform requests with Alamofire, but if you do API requests with some token in HTTP headers, you maybe don't need credentials store at all. So we can disable it for our request:

let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = ourHeaders
// disable default credential store
configuration.urlCredentialStorage = nil

let manager = Alamofire.SessionManager(configuration: configuration)
...

No errors after such change.

Gleb Tarasov
  • 795
  • 8
  • 15
4

In my case, I was not initialising Stripe SDK with API key.

        STPPaymentConfiguration.shared().publishableKey = publishableKey

In case of any Stripe operation, we can print the error log, its easy to understand.

        print(error.debugDescription)
preetam
  • 4,341
  • 2
  • 23
  • 52
4

This same issue happens to me and I found that if your API URL does not contain a "/" at the end of URL then iOS does not send "Authorization" value to the server. Due to which you will see a message like posted in question in the console.

So Simply add "/" at the end of URL

https://example.com/api/devices/
Iqbal Khan
  • 4,416
  • 6
  • 41
  • 78
3

This is transport error, let's add transport permission like this in plist file:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

Be careful as that enables connection to any server from your app. Read more on App Transport Security before proceeding. See comment by @kezi

Zaphod
  • 5,766
  • 2
  • 33
  • 52
tuan nguyen
  • 123
  • 1
  • 1
  • I don't know why this gets downvotes, this solution helped me! I have had problems with audiostream via FRadioPlayer https://github.com/fethica/FRadioPlayer – caffeinum Mar 23 '18 at 14:04
  • 9
    @caffeinum Because this removes any security what so ever. This is not an error on the part of the software. This is added in to give a barrier of protection to your app. This answer says nothing about that or what arbitrary loads means. – keji Mar 25 '18 at 07:14
  • Apple's app review will probably flag this and you'll be asked why your app needs to connect to arbitrary hosts. They may reject the app if they don't like your answer. It's much better to add a key for the specific hostname you're trying to connect to. – Jens Alfke Jul 25 '19 at 00:27
2

I edited the String that contains the URL to fix this issue:

var myUrl = "http://myurl.com"
myUrl = myUrl.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!

let url = URL(string: myUrl)
Pavlos
  • 828
  • 1
  • 10
  • 28
2

If you get this error, when using AVPlayer, just call .play() on main thread

  • With AVPlayer - I'm not calling play but loading assets and then call pause, but still got this warning. – Jonny Aug 22 '18 at 08:08
2

The cause of me getting this error was due to me accidentally using two spaces between the "Bearer" and access token in my Authorization header.

Incorrect:

request.setValue("Bearer  \(accessToken)", forHTTPHeaderField: "Authorization")

Correct:

request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

Simple mistake, but it took a while to find it.

TALE
  • 695
  • 10
  • 20
1

OK, I had this error, and fought with it for a long time (years) when interacting with my Ruby on Rails app.

I had default credentials set up as described in the accepted answer, but still got the error, and have been relying on a didReceiveChallenge response to supply the credentials - fortunately that worked as a work around.

But! I've just found the solution!

I was working on a hunch that that the protectedSpace fields did not match the Authorization challenge from the Ruby on Rails server - and I looked into the realm field, which seemed to be the only one that was being left undefined.

I started by printing out the server response headers, and although I was able to examine these, they did not include the WWW-Authorization field that would have included the realm field.

I thought this was maybe because my Rails app wasn't specifying the realm, so I started looking at the Rails side of things.

I found I could specify the realm in the call to,

authenticate_or_request_with_http_basic

...which I am using for HTTP Basic authentication.

I wasn't specifying a realm already, so added one,

authenticate_or_request_with_http_basic("My Rails App")

I then added the corresponding string to the protectionSpace,

NSURLProtectionSpace *protectionSpace =
    [[NSURLProtectionSpace alloc] initWithHost:@"myrailsapp.com"
        port:443
        protocol:NSURLProtectionSpaceHTTPS
        realm:@"My Rails App"
        authenticationMethod:NSURLAuthenticationMethodHTTPBasic];

Voila! That worked, and I no longer get the,

CredStore - performQuery - Error copying matching creds.  Error=-25300

Even after specifying the realm in the Rails app, I still don't see it passed in the HTTP header, I don't know why, but at least it works.

Snips
  • 6,063
  • 6
  • 36
  • 56
0

The error may also be caused by a Content Security Policy (CSP) that may be too restrictive. In our case, we needed a CSP that is more or less completely open and allows everything. Keep in mind that opening the CSP can be a great security issue (depending on what exactly you're doing in the app).

0

I got this issue when I tried to open a http-page inside a web-view. But this page contained an popup which was opened first.

When backend team removed this popup everything became OK.

Serge Maslyakov
  • 1,371
  • 1
  • 16
  • 21
0
    let credentialData = "\(user):\(password)".data(using: String.Encoding.utf8)!
    let base64Credentials = credentialData.base64EncodedString(options: [])
    let headers = ["Authorization": "Basic \(base64Credentials)"]
    Alamofire.request(url, method: .get, parameters: params,encoding: URLEncoding.default,headers: headers)
                .responseJSON{
            response in
            guard let value =  response.result.value else {return}
                    print(value)
     }
0

My issue was base64 encoding of an image that was being sent with a rest call

I had previously used

let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)

But 50% of the time I would get the error above.

I used the following instead which solved my problem...

 let strBase64 = imageData.base64EncodedString()
user139816
  • 193
  • 13
0

Had the same issue with Twitter sign in. Turned out I used the the wrong API key.

inokey
  • 3,243
  • 3
  • 18
  • 28