Curl is not sending client certificate - ssl

I am trying to send a simple curl request:
curl -k -i --key ./key.pem --cert ./cert.pem https://target_ip/whatever/
The problem I'm having is that it does not send any certificate. The validation clearly passes as otherwise I was getting errors such as the key does not match but then I can see in wireshark that the certificates are not being sent in the TCP connection around Client Hello. Switches like --verbose or --cacert don't do much either.
I am able to send the very same certificates through postman successfully.
I have tried sending the same curl request from various sources such as my WSL2 ubuntu, a debian container in the cloud, a VM, ...
Any tips why it is not sending the certs?
EDIT I - output from curl -v
* Trying 52.xxx.xxx.xx:443...
* TCP_NODELAY set
* Connected to 52.xxx.xxx.xx (52.xxx.xxx.xx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* 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-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=NGINXIngressController
* start date: Aug 10 18:08:13 2020 GMT
* expire date: Aug 10 18:08:13 2021 GMT
* issuer: CN=NGINXIngressController
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /whatever/ HTTP/1.1
> Host: custom.localhost.dev
> User-Agent: curl/7.68.0
> Accept: */*
> Authorization: Bearer eyJ0...
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
< Server: nginx/1.19.0
Server: nginx/1.19.0
< Date: Mon, 10 Aug 2020 22:23:24 GMT
Date: Mon, 10 Aug 2020 22:23:24 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 153
Content-Length: 153
< Connection: keep-alive
Connection: keep-alive
<
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>
* Connection #0 to host 52.xxx.xxx.xx left intact
EDIT II - wireshark captures
It seems to be too much of a hassle to anonymise pcap, so here's just some snaps. Hopefully you'll be able to see all you need. I have highlighted the packet where I do (not) see the cert being sent. Note that I am running the postman on my windows workstation, whereas the curl is in the WSL2, hence the different source addresses. Other hosts for curl did behave the same though.
Curl
Postman
EDIT III - Client Hellos
Curl
Postman

The ClientHello shows a clear difference: postman uses the server_name extension (SNI) to provide the expected hostname while curl does not.
This likely triggers a different part of the configuration in the web server: postman triggers access to the specific virtual host given as server_name while curl will probably run into the default configuration. Assuming that only the specific virtual host enables client certificates this explains why the CertificateRequest is send by the server only to postman but not to curl.
It is unclear what this hostname is, but based on the length it cannot be an IP address. Thus postman somehow must know the expected hostname of the server even though it is claimed that the access was done with https://target_ip/ only, i.e. without a given hostname. curl cannot derive from this URL the expected hostname and thus cannot set server_name. To make curl be aware of the hostname to set server_name while still being able to access a specific IP use the --resolve option:
curl --resolve hostname:443:target_ip https://hostname/

Related

TLS certification expired only for some users

I have a k8s cluster with an ingress nginx as a reverse proxy. I am using letsencrypt to generate TLS certificate
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ******
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
Everything worked fine for months. Today,
$ curl -v --verbose https://myurl
returns
* Rebuilt URL to: https://myurl/
* Trying 51.103.58.**...
* TCP_NODELAY set
* Connected to myurl (51.103.58.**) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, Server hello (2):
* SSL certificate problem: certificate has expired
* stopped the pause stream!
* Closing connection 0
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
HTTPS-proxy has similar options --proxy-cacert and --proxy-insecure.
For 2 other people on my team, error is the same and I have the same error when I use Postman (expired certificate).
But for another one, we get no error :
* Trying 51.103.58.**...
* TCP_NODELAY set
* Connected to myurl (51.103.58.**) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (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 change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=myurl
* start date: Jul 24 07:15:13 2021 GMT
* expire date: Oct 22 07:15:11 2021 GMT
* subjectAltName: host "myurl" matched cert's "myurl"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fd9be00d600)
> GET / HTTP/2
> Host: myurl
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< server: nginx/1.19.1
< date: Thu, 30 Sep 2021 16:11:23 GMT
< content-type: application/json; charset=utf-8
< content-length: 56
< vary: Origin, Accept-Encoding
< access-control-allow-credentials: true
< x-xss-protection: 1; mode=block
< x-frame-options: DENY
< strict-transport-security: max-age=15724800; includeSubDomains
< x-download-options: noopen
< x-content-type-options: nosniff
< etag: W/"38-3eQD3G7Y0vTkrLR+ExD2u5BSsMc"
<
* Connection #0 to host myurl left intact
{"started":"2021-09-30T13:30:30.912Z","uptime":9653.048}* Closing connection 0
When I use my web browser to go to the website, everything works fine and the certificate is presented as valid and for now, I get no error in prod or staging environment. (same error on staging)
Has anyone an explanation on this ?
Warning! Please plan OS upgrade path. The below advice should be applied only in emergency situation to quickly fix a critical system.
Your team missed OS update or ca-certificates package update.
Below solution works on old Debian/Ubuntu systems.
First check if you have offending DST Root CA X3 cert present:
# grep X3 /etc/ca-certificates.conf
mozilla/DST_Root_CA_X3.crt
Make sure the client OS have the proper ISRG Root X1 present too:
# grep X1 /etc/ca-certificates.conf
mozilla/ISRG_Root_X1.crt
This is going to disable X3:
# sed -i '/^mozilla\/DST_Root_CA_X3/s/^/!/' /etc/ca-certificates.conf && update-ca-certificates -f
Try curl https://yourdomain now, should pass.
Again, plan an upgrade please.
This is related to the expired DST Root CA X3, which expired Sep 30 14:01:15 2021 GMT.
The DST CA Root X3 certificate is part of the "cacert-bundle".
As of today the "cacert-bundle" can be found here: https://curl.se/docs/caextract.html
as part of the bundle https://curl.se/ca/cacert.pem.
The expired certificate is:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
44:af:b0:80:d6:a3:27:ba:89:30:39:86:2e:f8:40:6b
Signature Algorithm: sha1WithRSAEncryption
Issuer: O=Digital Signature Trust Co., CN=DST Root CA X3
Validity
Not Before: Sep 30 21:12:19 2000 GMT
Not After : Sep 30 14:01:15 2021 GMT
Subject: O=Digital Signature Trust Co., CN=DST Root CA X3
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Which is used to verify peer in curl calls to websites using Let's Encrypt issued certificates.
Here's a detailed solution to your problem: https://stackoverflow.com/a/69411107/1549092
Let's Encrypt formal address of the issue can be found here: https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021/
Even if not K8S related, main explanation is contained in :
Sudden OpenSSL Error messages: error:14090086 using file_get_contents . I complete it with K8S related here.
I fixed the same issue by upgarding my certbot and reissuing certificate with `` --preferred-chain 'ISRG Root X1'
you can do the same with options in the yaml of the cert issuer :
see here : https://cert-manager.io/docs/configuration/acme/#use-an-alternative-certificate-chain
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
preferredChain: "ISRG Root X1"

Is Mutual TLS supposed to be performed during TLS handshake only?

Recently I've been evaluating different API Gateway (API GW) options for the IoT-based project. The purpose of this was to find a good enough solution for performing Mutual TLS (mTLS) authentication of the devices and API GW.
Most of the solutions I've tried out seem to perform mTLS during the TLS handshake as nicely depicted here. So this is what I understand OSI Layer 4 (TCP/IP) authentication method.
However, the Kong API Gateway seem to do it at OSI Layer 7 (Application). Basically, no client auth during the TLS handshake phase, and rather application layer validates the peer certificate. Hence it's able to send the response with 401 status and some payload (which is not possible, if TLS handshake fails). Example
√ poc-mtls-local-env % make test-fail-wrong-cert master
curl -v --cacert certs/gen/ca-chain.crt \
--key certs/gen/device.key \
--cert certs/gen/device.crt \
https://mtls.auth.local.com/echo
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to mtls.auth.local.com (127.0.0.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: certs/gen/ca.crt
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (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, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS handshake, CERT verify (15):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=NY; L=NYC; O=Sample; OU=UDS; CN=local.com
* start date: Jul 29 12:10:25 2021 GMT
* expire date: Jul 29 12:10:25 2022 GMT
* subjectAltName: host "mtls.auth.local.com" matched cert's "mtls.auth.local.com"
* issuer: C=US; ST=NY; O=Sample; OU=UDS; CN=Sample Intermediate CA; emailAddress=it#sample.com
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fc0dd808200)
> GET /echo HTTP/2
> Host: mtls.auth.local.com
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 401
< date: Tue, 10 Aug 2021 06:46:13 GMT
< content-type: application/json; charset=utf-8
< content-length: 49
< x-kong-response-latency: 4
< server: kong/2.4.1.1-enterprise-edition
<
* Connection #0 to host mtls.auth.local.com left intact
{"message":"TLS certificate failed verification"}* Closing connection 0
We can clearly see that request goes past the TLS handshake successfully, and the application layer forms 401 response with {"message": "TLS certificate failed verification"}.
This made me think of the following questions:
Formally speaking, can it also be called mTLS what Kong does here?
Are there any potential pitfalls with such an approach?
Most of the solutions I've tried out seem to perform mTLS during the TLS handshake as nicely depicted here. So this is what I understand OSI Layer 4 (TCP/IP) authentication method.
Since TLS is above layer OSI layer 4 the authentication is also above layer 4. But OSI layers aside (which don't sufficiently match today's reality above layer 4 anyway) you essentially ask at what stage the mutual authentication happens.
Mutual authentication in TLS happens in two stages: requesting the clients certificate and validating that the certificate matches the requirements. Requesting the certificate is always done inside the TLS handshake, although it does not need to be the initial TLS handshake of the connection.
Validating the certificate can be done inside the TLS handshake, outside of it or a combination of both. Typically it is checked inside the handshake that the certificate is issued by some trusted certificate authority, but further checks for a specific subject or so might be application specific and will thus be done after the TLS handshake inside the application. But it might also be that the full validation is done inside or outside the TLS handshake.
Accepting any certificates inside the TLS handshake and validating the certificate then outside the handshake only, has the advantage that one can return a useful error message to the client inside the established TLS connection. Validation errors inside the TLS handshake instead result in cryptic errors like handshake error alerts or just closing the connection, which are not that helpful to debug the problem.

How to use 'curl' to call a secure (https) WCF service - GET request only

The context is i created a WCF Service, hosted in IIS using https.
I have no issues with the WCF Service itself, it is working as it should; I can navigate to the service page at
https://myhost/VirtualAppOnIIS/Some/WCF/Service/Here/V1
using a Browser (IE in my case).
The "lock" symbol displays ok, and i can view the certificate info; More cert info is:
root CA is Verisign, which issued a Verisign Intermediate cert, which issued
my server cert (let's call it "myhost")
"Key Usage" set as critical, purposes are: Digital Signature, Non-Repudiation, Key Encipherment, Data Encipherment (f0)
The "Extended Key Usage" is absent, so i can conclude it is undefined / not set by the certificate issuer (and therefore this cert can be used as both Server cert or Client cert)
So far so good. My real issue is how to get curl to make a /GET https request (similar to the way the Browser does it).
Attempt #1.
curl --tlsv1.2 https://myhost/VirtualAppOnIIS/Some/WCF/Service/Here/V1 -v
* Trying 192.168.1.114...
* TCP_NODELAY set
* Connected to myhost (192.168.1.114) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: C:\SETUPS\curl\curl-ca-bundle.crt CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS alert, Server hello (2):
* SSL certificate problem: unsupported certificate purpose
* stopped the pause stream!
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, Client hello (1): curl: (60) SSL certificate problem: unsupported certificate purpose
More details here: https://curl.haxx.se/docs/sslcerts.html
...etc ...
If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.
We can see an error after server hello (2):
SSL certificate problem: unsupported certificate purpose
I made sure I have both certificates for Intermediate and Root CA concatenated within the file curl-ca-bundle.crt (and nothing else), which curl finds by default, and i don't believe it's a chain validation issue, seems a cert purpose problem as suggested by the error message.
Attempt #2
Bybass https validation, as suggested by the curl output, using the -k switch. Yes, it works !
curl --tlsv1.2 https://myhost/VirtualAppOnIIS/Some/WCF/Service/Here/V1 -v -k
* 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, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=country; ST=state; O=Some Company PTY LIMITED; CN=myhost
* start date: Apr 26 00:00:00 2017 GMT
* expire date: Mar 29 23:59:59 2019 GMT
* issuer: O=VeriSign; OU=Whatever PKI; CN=Whatever Intermediate CA
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
GET /VirtualAppOnIIS/Some/WCF/Service/Here/V1 HTTP/1.1
Host: myhost
User-Agent: curl/7.53.1
Accept: */*
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/8.5
Set-Cookie: ASP.NET_SessionId=iy1s4q1hwkncywi5m0w0coch; path=/; HttpOnly
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 02 May 2018 07:08:30 GMT
Content-Length: 3236
<HTML><HEAD>
etc... etc... more html for wcf service page... etc ... etc...
</BODY></HTML>
Connection #0 to host myhost left intact
So to re-phrase the question, if it is a cert. purpose issue (as suggested in attempt #1), what cert. purposes or settings or configurations are required (when issuing the cert) to make curl and WCF with TLS work ?
Incidentally i am using curl on Windows from https://winampplugins.co.uk/curl/

Xively REST API with cURL - 403 Forbidden

I'm trying to follow the xively cURL tutorial. I have created new device in develop mode, copied the default auto-generated API key (with READ, WRITE, CREATE, DELETE permissions) to the example in tutorial and get response:
{"title":"Forbidden","errors":"You do not have the necessary permissions to access this resource"}
I must be missing some obvious step. Do I need to activate the API key somehow before using it in scripts?
The cURL command:
curl --request POST \
--data '{"title":"My feed", "version":"1.0.0"}' \
--header "X-ApiKey: cPHLfGw1WJdMAbU8FzbfsdFyJ8suayHEH3OChRrkpYwQCmrb" \
--verbose \
https://api.xively.com/v2/feeds
full verbose output:
* About to connect() to api.xively.com port 443 (#0)
* Trying 216.52.233.120...
* Connected to api.xively.com (216.52.233.120) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using ECDHE-RSA-RC4-SHA
* Server certificate:
* subject: C=US; postalCode=01801; ST=MA; L=Woburn; street=First Floor; street=500 Unicorn Park Drive; O=LogMeIn Inc.; OU=Secure Link SSL Wildcard; CN=*.xively.com
* start date: 2013-05-07 00:00:00 GMT
* expire date: 2014-04-27 23:59:59 GMT
* subjectAltName: api.xively.com matched
* issuer: C=US; O=Network Solutions L.L.C.; CN=Network Solutions Certificate Authority
* SSL certificate verify ok.
> POST /v2/feeds HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.xively.com
> Accept: */*
> X-ApiKey: cPHLfGw1WJdMAbU8FzbfsdFyJ8suayHEH3OChRrkpYwQCmrb
> Content-Length: 38
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 38 out of 38 bytes
< HTTP/1.1 403 Forbidden
< Date: Sat, 30 Nov 2013 11:03:15 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 98
< Connection: keep-alive
< X-Request-Id: 6cbb9676b448a4967187271dd246b423f7da2e39
<
* Connection #0 to host api.xively.com left intact
{"title":"Forbidden","errors":"You do not have the necessary permissions to access this resource"}
It depends what you are trying to do. POST requests to api.xively.com/v2/feeds are no longer supported with any API key. This is because, since the implementation of devices, programatic creation of feeds directly is no longer supported.
This is an oversight in the Xively tutorial and I will inform the appropriate people to make sure that it gets changed.
In the mean time, since you have already created a device, you are basically ready to start the cURL tutorial at step 3 "Update a Feed". Use the API key and Feed ID from the development device you have already created on the website. Make sure to change your URL, body, and from a POST request to a PUT request.
I think you need to add your feed id onto the end of the URL.

Github Api v3 giving 404 when I try to create a repo

I've executed the following command with the respective response.
However, if I try to get information about the /user, it works, witch means that my token is valid.
What Am I doing wrong?
guto#willie:~/$ curl -v -XPOST -H 'Authorization: token S3CR3T' -H 'Content-Type: application/json; charset=utf-8' https://api.github.com/user/repos -d '{"name":"my-new-repo","description":"my new repo description"}'
Output:
* About to connect() to api.github.com port 443 (#0)
* Trying 207.97.227.243... connected
* Connected to api.github.com (207.97.227.243) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using AES256-SHA
* Server certificate:
* subject: O=*.github.com; OU=Domain Control Validated; CN=*.github.com
* start date: 2009-12-11 05:02:36 GMT
* expire date: 2014-12-11 05:02:36 GMT
* subjectAltName: api.github.com matched
* issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certificates.godaddy.com/repository; CN=Go Daddy Secure Certification Authority; serialNumber=07969287
* SSL certificate verify ok.
> POST /user/repos HTTP/1.1
> User-Agent: curl/7.21.3 (x86_64-pc-linux-gnu) libcurl/7.21.3 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.18
> Host: api.github.com
> Accept: */*
> Authorization: token S3CR3T
> Content-Type: application/json; charset=utf-8
> Content-Length: 62
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.0.4
< Date: Tue, 27 Dec 2011 03:45:12 GMT
< Content-Type: application/json; charset=utf-8
< Connection: keep-alive
< Status: 404 Not Found
< X-RateLimit-Limit: 5000
< ETag: "31b00b4920d3470b70611b10e0ba62a7"
< X-OAuth-Scopes: public_repo, user
< X-RateLimit-Remaining: 4976
< X-Accepted-OAuth-Scopes: repo
< Content-Length: 29
<
{
"message": "Not Found"
}
* Connection #0 to host api.github.com left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):
guto#willie:~/projetos/apostilas/4linux-helper$
Check the Oath Scope GitHub documentation:
$ curl -H "Authorization: bearer TOKEN" https://api.github.com/users/technoweenie -I
HTTP/1.1 200 OK
X-OAuth-Scopes: repo, user
X-Accepted-OAuth-Scopes: user
You need to have the repo scope in order to have the right to create a repo, as illustrated by the SO question "Github v3 API - create a REPO".
repo
DB read/write access, and Git read access to public and private repos.
NOTE: Your application can request the scopes in the initial redirection.
You can specify multiple scopes by separating them by a comma.
https://github.com/login/oauth/authorize?
client_id=...&
scope=user,public_repo
try using
curl -v -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d '{"name":"my-new-repo","description":"my new repo description"}' https://api.github.com/user/repos?access_token=S3CR3T