nhosoya / omniauth-apple

OmniAuth strategy for Sign In with Apple
MIT License
260 stars 99 forks source link

Fetching keys fails in production #70

Closed ConfusedVorlon closed 1 year ago

ConfusedVorlon commented 3 years ago

in production, fetch_jwks fails with a 403 error

I don't think it is a problem with my server as running simple curl from the server works fine

curl https://appleid.apple.com/auth/keys
> returns keys

opening the rails console and using Net:HTTP

Loading production environment (Rails 6.1.3)
irb(main):001:0> uri = URI.parse('https://appleid.apple.com/auth/keys')
=> #<URI::HTTPS https://appleid.apple.com/auth/keys>
irb(main):002:0> response = Net::HTTP.get_response(uri)
=> #<Net::HTTPForbidden 403 Forbidden readbody=true>
irb(main):003:0> response.body
=> "<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body>\r\n<center><h1>403 Forbidden</h1></center>\r\n<hr><center>Apple</center>\r\n</body>\r\n</html>\r\n"

any ideas?

btalbot commented 3 years ago

I've seen some other issues complaining about this happening when there is no User-Agent included in the request. Since the Net::HTTP client has a default User-Agent my guess is that some other software in your stack has disabled sending the User-Agent header by Net::HTTP for some reason.

What happens if you manually configure the user-agent in Net::HTTP? If that works, then either set that in your stack or find what is preventing it from using the default value provided by the Net::HTTP library.

ConfusedVorlon commented 3 years ago

thanks for the response.

I'll give that a whirl. Do you know what the User-Agent should be? The apple endpoint docs don't say anything about a user-agent requirement...

btalbot commented 3 years ago

Currently, it seems to default to Ruby and that has been the case for quite some time. See https://github.com/ruby/net-http/blob/master/lib/net/http/generic_request.rb#L48

FWIW, apple doesn't seem require any user-agent when I make the call -- but others have reported that they do, so /shrug

curl -A '' -v --url https://appleid.apple.com/auth/keys
*   Trying 17.111.105.242:443...
* Connected to appleid.apple.com (17.111.105.242) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: businessCategory=Private Organization; jurisdictionC=US; jurisdictionST=California; serialNumber=C0806592; C=US; ST=California; L=Cupertino; O=Apple Inc.; OU=IdMS Operations; CN=appleid.apple.com
*  start date: Jun  9 00:00:00 2020 GMT
*  expire date: Jun  9 12:00:00 2021 GMT
*  subjectAltName: host "appleid.apple.com" matched cert's "appleid.apple.com"
*  issuer: C=US; O=DigiCert, Inc.; OU=www.digicert.com; CN=DigiCert SHA2 Extended Validation Server CA-3
*  SSL certificate verify ok.
> GET /auth/keys HTTP/1.1
> Host: appleid.apple.com
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Server: Apple
< Date: Wed, 03 Mar 2021 20:12:08 GMT
< Content-Type: application/json;charset=ISO-8859-1
< Content-Length: 1439
< Connection: keep-alive
< Cache-Control: no-store
< Pragma: no-cache
< Host: appleid.apple.com
ConfusedVorlon commented 3 years ago

ok - so, I believe I have pinned it down. Apple are being dicks. I set up a quick service to check what ua was actually being sent, and 'Ruby' is the default user agent for Net:HTTP in my setup (no idea why)

curl -A 'Ruby' -v --url https://appleid.apple.com/auth/keys
-> 403
curl -A '' -v --url https://appleid.apple.com/auth/keys
-> 200

In Ruby, Manually setting the user agent to be blank does the job (there may be a better way...)

#this works
uri = URI.parse("https://appleid.apple.com/auth/keys")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri)
request['user-agent'] = ""
response = http.request(request)
btalbot commented 3 years ago

Must be a regional thing then, cause apple seems fine with a Ruby user-agent for me. I'm very near Cupertino though so ...

curl -A 'Ruby' -v --url https://appleid.apple.com/auth/keys
*   Trying 17.111.105.242:443...
* Connected to appleid.apple.com (17.111.105.242) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: businessCategory=Private Organization; jurisdictionC=US; jurisdictionST=California; serialNumber=C0806592; C=US; ST=California; L=Cupertino; O=Apple Inc.; OU=IdMS Operations; CN=appleid.apple.com
*  start date: Jun  9 00:00:00 2020 GMT
*  expire date: Jun  9 12:00:00 2021 GMT
*  subjectAltName: host "appleid.apple.com" matched cert's "appleid.apple.com"
*  issuer: C=US; O=DigiCert, Inc.; OU=www.digicert.com; CN=DigiCert SHA2 Extended Validation Server CA-3
*  SSL certificate verify ok.
> GET /auth/keys HTTP/1.1
> Host: appleid.apple.com
> User-Agent: Ruby
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Server: Apple
< Date: Wed, 03 Mar 2021 22:16:09 GMT
< Content-Type: application/json;charset=ISO-8859-1
< Content-Length: 1439
< Connection: keep-alive
< Cache-Control: no-store
< Pragma: no-cache
< Host: appleid.apple.com
ConfusedVorlon commented 3 years ago

that's just bizarre.

It seems like explicit empty user-agent may be the safe option. Would you accept a pull request if I make that change?

strangely - My London and Amsterdam servers are both fine with 'Ruby'. My New York server isn't. All running on Digital Ocean in broadly similar configurations.

btalbot commented 3 years ago

From AWS us-east-1 in Virginia is working fine with Ruby too.

nov commented 1 year ago

I believe this is not a problem anymore.