Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Deprecating password authentication in GitHub API (developer.github.com)
132 points by nlolks on April 12, 2020 | hide | past | favorite | 88 comments


Wondering when they will start with implementing proper access controls on their API's. At the moment, a personal access token does have scopes, but it is quite limited:

- Repo access is all or nothing. A read-only token is not possible, an 'issues-only' token is not possible.

- Personal access tokens are not scoped to repositories or organizations. So your personal toy project token also allows access to your super-sensitive employer's repository. On top of that, your employer is unable to prevent this, unless you start using Github Enterprise _and_ an SSH CA, which is far from trivial.

It's nice that they drop username/password access, but as long as personal access tokens have such broad permissions, it does not really add any value (you should have been using 2FA anyway).


What is really weird is this isn't quite correct, they do have scoped personal access tokens, you just can't make them. If you use GitHub actions, it generates a scoped PAT that only works for that repository for your actions to use.

I use deploy keys rather than a PAT as they can be scoped (single repo and can be read-only), but they are more work and are limited to git actions rather than the whole GitHub API.

The fact they clearly have the internal capability for this makes it incredibly odd they aren't exposing it for users to use, and I agree it'd be a really valuable thing to have.


GitHub Actions tokens are actually based off our newer “GitHub apps” system and not “OAuth apps”. GitHub app tokens support much more granular controls (both in terms of abilities and resources). OAuth doesn’t lend itself to super granular controls since they are scope based (ex. Defining a scope per repository doesn’t really scale). This whole area is something we want to address with personal access tokens in the future.


Adding to this wish list, the ability to rotate a token automatically. I'd like to do something like this with secrets manager, but GitHub's API just doesn't allow it - https://docs.aws.amazon.com/secretsmanager/latest/userguide/...


Think of this deprecation as step one of a multi-step plan/roadmap .


What is the roadmap for supporting an Action that can push a commit (say a version bump) to a protected branch?


GitHub Apps has per repo authorizations...


> During a brownout, password authentication will temporarily fail to alert users who haven't migrated their authentication calls.

This took me a second to correctly parse. Would have been better written as: “During a brownout, password authentication will temporarily fail. This is to alert users who haven't migrated their authentication calls.”


Aside: this is the English language version of spreading a bunch of ideas across multiple lines of code instead of one mega line of code.


Even kept as one sentence it could be much clearer: “To alert users who haven't migrated their authentication calls, during a brownout, password authentication will temporarily fail.”


This confused me too. It also confused me that they only occur for 3 hour periods on 2 specific days. You wouldn't be "alerted" unless you happened to attempt login during those windows.

Can anyone provide more context for this deprecation strategy?


Best to compare Brownout to other strategies that get to the same end result. The goal is that this feature (password authentication) goes away. A common default is a flag day. There's an announcement (maybe now) and on a set date that feature just goes away.

For users who pay attention (say, us) and prioritise accordingly these strategies are the same, they know the feature it going away and can plan for that.

But for users who weren't paying attention or who didn't correctly prioritise, adding a Brownout offers some final warning that helps push more people to start preparing before the final flag day happens.

It doesn't need to get everyone, if 80% of users whose business processes still depend upon password authenticated GitHub notice something went wrong, and during diagnosis discover that what went wrong is they're relying on a deprecated feature, that's a big improvement over 100% of those processes dropping dead on flag day.

Brownout is a desirable choice where you're sure that some large population will not heed the advance notice. I bet that a lot of corporate GitHub setups have all contact mail from GitHub either going to /dev/null or to some business person who hasn't the first clue what "password authentication on the GitHub API" is. Maybe they'll email the right dev person, maybe they forward to an employee who left six months ago, either way it's far from certain anybody who needs to take action will learn from an email.

With UX feature deprecation you can tell the live users of the service. But in APIs even if you notionally have a way to feed stuff back (like a "warnings" field in the results) it's probably blackholed by lazy programmers or lands in a debug log nobody reads. So "It stopped working" is the best way to get attention, but without a Brownout that's permanent. The user learns what's wrong too late to do much about it which sucks.

Brownout is something ISRG's Let's Encrypt has used, because of course Let's Encrypt is largely an API too, they publish feature changes but a huge fraction of all their subscribers aren't paying attention so the Brownout is the first they'll know anything is happening that matters to them.


> Best to compare Brownout to other strategies that get to the same end result.

Sure, the isolated period blackout (“brownout” is a bad metaphor) of the deprecated function has some obvious communicative utility compared to flag day, but once you accept shut-off for communication, it kind of immediately suggests communication methods that have a stronger guarantee of reaching the audience, like progressively frequent blackouts (or probabilistic denials) over a period of time leading to total shutoff.


As I understand it, any API call using the deprecated authentication scheme will fail for the 3-hour period, not just logins.

So for some folks, maybe CI will be broken, or deployment automation, or even code review.

The trade-off here is to be disruptive enough that folks will notice and fix old callers of the API, while not leaving thousands of coders permanently in the lurch (they'll notice and complain, but three hours later they can get back to work, while someone fixes the infrastructure in the meantime).


They might have determined that the bulk of the accounts that were going to authenticate (active accounts) would do so during these periods so they'd reach the vast majority of accounts without breaking the systems using those accounts severely. This might be better than refusing we queries at random, I think.


What isn’t stated in that post is that we are sending monthly email notifications to any user found using password authentication during the deprecation. As a result, we expect the vast majority of users will have been notified several times before the brownout. The brownout is mostly aimed at unearthing any forgotten automations that will break when we disable support for password authentication permanently.


They're going to make the service fail during a known period so people will know they haven't migrated.


We updated the language, thanks for pointing that out.


Just putting a comma after "fail" would fix it.


What is not secure about using HTTP basic auth over a properly secured HTTPS connection?


We similarly deprecated password auth on our API previously. We used to allow basic auth over HTTPS.

Two issues:

* users will ultimately hard code the passwords in a script

* the user may have used the same password on other sites

Combine the above together and it can result in a bad situation.

It's best for a vendor (like GitHub) to encourage good security, where possible. A token which is unlinked to the password and can be revoked independently of the password adds minimises the extend of the compromise.


Did you end up using the token with HTTP basic auth over HTTPS? Or did you switch to something else to transport the auth token?


Authorization: Bearer <token>

Ultimately similar to what github did..


Perhaps not about the security of basic auth per se, but if you are using basic auth then setting up mfa is a little more painful as you first need to migrate all your API access to tokens before you can change to mfa. If you're already using tokens then turning on mfa is just flipping a switch and scanning your totp code.


What would be nice is if Github would allow one factor of authentication via a client side TLS certificate. That's what's essentially being done when one clones a repo via SSH since Github has a copy of the account holder's SSH public key.

That is, 2FA could be achieved via use of that certificate and a username/password.


One issue with HTTPS client cert auth is that it can be non-trivial to support at the application level when you have a multi-tier architecture where TLS termination happens at the edge of your infrastructure.


I wonder if there are any solutions out there that can handle TLS client cert verification along with validating the username/password (which, if provided via HTTP basic auth, would be in the header of the request). That way, the application itself could just concern itself with serving resources, interacting with resources, etc instead of handling authentication or authorization.

The infrastructure edge device could communicate additional information if needed by adding headers to the original HTTP request when it's passed down to the endpoint that actually handles the request.


Can client side certificates be "locked" in the same way that SSH keys can (where you require a passphrase before it is loaded into the ssh agent)?


When you generate a private key using openssl, it will prompt you for a passphrase.


Haven’t read the article yet but I will be surprised if it claims that. I would imagine it’s more about using your primary means (password) of authn which has worse consequences than using a secondary, revocable means (token) upon compromise.


The blog post[1] that the article links to does state:

>> We are announcing deprecations that will improve the security of GitHub apps and APIs

[1] https://developer.github.com/changes/2019-11-05-deprecated-p...


It’s not at all about the security of delivering credentials over https, but more about the the complexity of trying to defend against weak passwords/credential stuffing with an api. For example, it’s more or less impossible to add a defense in depth flow like https://github.blog/changelog/2019-07-01-verified-devices to an api.


> it’s more or less impossible to add a defense in depth flow like https://github.blog/changelog/2019-07-01-verified-devices to an api.

Except that email, as described in the blog you linked to, is not a secure means of communication. What would be secure is to use a client side TLS certificate as part of the authentication process. That is, your browser/device sends it as part of the TLS connection negotiation process and then you authenticate via the username and password (via HTTP basic auth).

They're already doing something like that whenever one pushes or fetches from a git repository hosted on Github through ssh key authentication. It wouldn't be much of a stretch for Github to allow an account holder to upload a CSR and then Github signs it and makes a certificate, which the account holder can then add to the browser's or OS's certificate store.


The verified device flow isn’t meant to be as strong as 2FA, but is a very strong mitigation against mass credential stuffing attacks for all users.

In terms of client certs, see my response in https://news.ycombinator.com/item?id=22849985. I agree client certs would be great. However, it can be tricky to couple your app logic with transport based security. A good example of this...chrome/google introduced a crazy cool concept called “channel bound cookies” - http://www.browserauth.net/channel-bound-cookies, but it never gained any traction because of the complexity noted.


A comment below also points out the token ensures a higher quality secret is being used most of the time.

Edit: typo


Mostly poor quality passwords and password re-use are the problem. The replacement tokens are generated by GitHub, so you can't choose "bad" ones, and if you were to re-use them it ought to be pretty clear that's crazy since GitHub chose them in the first place.


Tokens (in general, not specifically GitHub's PATs) have more fine-grained permissions and can be revoked / rotated more easily.


It's about the password management. Users get tempted into storing their passwords in plain text in env, config files, code etc.


Feature request: allow association of the same ssh key with multiple accounts.

In essence stop using git username globally and start supporting user names.


Why would you want this though? Your multiple git accounts are not the same identity.


SSH treats the key as password, you can have the same authorized key associated with multiple accounts.

Not sure why you choose to look at the key as identity.


SSH treats your key as evidence of your identity.

You can choose to give the public half of your key to multiple entities to allow them to verify your possesion of the private half of the key but that does not translate into multiple identities.


Not sure why I can't get my point across. It's simple really:

Can you use the same ssh key to ssh into different accounts on the same system?


Ah I see, yes, you're right.


The main way I've found this to be annoying is GitHub "Deploy Keys"[1]. They treat them similar to users, so you need a unique deploy key per repository. That is pretty annoying when trying to authenticate something like a CI server.

The main alternative is "Machine Users"[1], which are actually normal user accounts. That means they have the same policies as regular users, like mandated 2FA for an organization. And to manage them you have to log-in as that user. That makes it a pain for a team to manage a Machine User.

GitHub really needs to have Service Accounts that belong to an organization, and can be managed by admins of the organization (without having to log-in as the Service Account). The Service Accounts should be able to have SSH keys and API tokens associated with them.

[1] https://developer.github.com/v3/guides/managing-deploy-keys/


I was once told explicitly by GitHub Support (just as a reminder) that one person having multiple accounts is against their TOS, so there’s that. (This was years ago, not sure if TOS has changed in this aspect.)


The same person creating separate accounts for automation is explicitly permitted however: https://help.github.com/en/github/getting-started-with-githu...


Their Terms of Service (https://help.github.com/en/github/site-policy/github-terms-o...) say: One person or legal entity may maintain no more than one free Account (if you choose to control a machine account as well, that's fine, but it can only be used for running a machine).


I was told by GitHub Support less than a month ago that in order for Actions to trigger other Actions I'd need to make a new separate account with repo access and have them act using its PAT.


I have one free personal account and a paid account for work. So I don’t think it’s against their TOS


wat

Never heard such a restriction even mentioned, let alone enforced.


Well you just heard. At least they say “we do not recommend creating more than one account” at the moment. https://help.github.com/en/github/getting-started-with-githu...

Enforced — of course not (guess why I was told), but it stands to reason that they probably won’t add a feature to facilitate TOS violation.


GitHub is not what it used to be when this "restriction" was made. These days, where a lot of companies decide to go with github, it's not uncommon for people to have one personal account and one work account.

This becomes messy to manage, as it's not easy(as far as I know) to use the same account on your personal PC to do both personal and work work.


Wont't work since the user is identified by his public key on the ssh level.


Is anyone else bothered by the use of "deprecating" to mean "removing"? Historically, deprecated features are ones that still exist, but their use is discouraged.


And it does still exist, until November. Deprecation is a transition period, instead of just removal without warning, but without future scheduled removal then deprecation would serve no purpose.


What I'm most worried about is the deprecation of Personal Access Tokens because I have yet to find the equivalent for doing something like "Create a Deployment with a single cURL request to the Github API" that will work past September.

I wish they replaced it by tokens tied to specific repos and with scopes instead of that new Webapp Flow thing that looks a lot more complicated to implement than a curl request (I had planned to look into it this month, but obviously other worldwide events took priority).


I think the auth method is slightly less important than the offered feature set. F.ex. you cannot ask if a specific user has sponsored you and for how much. This is probably the ONLY important feature to have an API for!

The only way to get this data now is to paginate through all sponsors with their GraphQL interface!


> All password authentication will return a status code of 401...

I’ve always found it strange that an HTTP 401 is used to indicate two very different server-side states:

• “this resource requires authentication, and you didn’t attempt authentication”

• “as an early step in the request flow, you tried to authenticate yourself—but your authentication failed (due to e.g. having an unrecognized username; or using the wrong authentication method; or, of course, having the wrong password)”

I mean, I get it; in the end, after trying and failing to authenticate, the request-processing continues (with the “auth” field in the server’s model of the request state being nil, just like it would be if you hadn’t attempted auth); and the request you’re making at that point is still an attempt to request an authentication-required resource. You’re “not authenticated” at that point, so 401 it is.

But it really seems like auth processing should have its own “off ramp” in the HTTP request-processing lifecycle—i.e. if you ask for auth, and auth fails, you get a code and the request isn’t processed any further, so it doesn’t matter that the request you made is auth-required.

(After all, we mentally model HTTP resources, fundamentally, as URLs; and URLs put the auth stuff in the origin part, not in the request sent to the origin part. I would naively expect that an auth failure would resolve at the same stage as an unrecognized Host name!)

When you’re coding an HTTP client, it’s very hard to debug a corrupt Authorization header, because all you know, when you have anything even slightly wrong, is that the server is pretending it didn’t see it!

-----

And yeah, I know, in practice, why this isn’t the way things are. Historically, one of the first uses of the Authorization header was through Apache’s mod_auth_basic, which refers to an .htpasswd file in a directory to determine the set of valid auth credentials for all resources descending from that directory. In this model, auth is resource-specific, rather than server-specific; so it makes sense that, if you’re sending auth, and auth is unrecognized, but the specific resource you’re authing against turns out to not require auth, then the server can proceed just fine without sending you a 401.

However, I don’t think there’s any modern use-case where auth is resource-specific like that. HTTP auth “realms” are almost always per-origin these days. It makes a lot more sense to think of auth as something happening at the level of an implicit HTTP gateway between the client and the server ultimately sending the resource, where the gateway can know what server (realm) the client wants to route to—and so can auth the client on that basis, and deny the request if that auth fails—but the gateway can’t know anything about what the auth requirement policies are for individual resources on the backend it’s sitting in front of.


Separating those cases expsoses the existence of an object, even if you can't access it.

Whether that matters is up to you, but I get the impression most people just default to not exposing existence. There is 403 which helps split these.


How does 403 help? Isn’t that for when authentication worked but authorization didn’t?


Correct. You’re supposed to send 403 only when 1. you’ve successfully “logged in” with a set of credentials, but 2. the user that those credentials map to, doesn’t have rights on the resource. If you haven’t authed at all, and there’s a resource there requiring auth, you’re supposed to send 401.


This usage of 403 should be used carefully. It's often (probably usually) the case that you still don't want to expose existence of a resource even to an authenticated user who is not authorized to that resource. It's generally better to return 404 in that case.


The distinction is whether the resource is owned by another tenant or not. Often a user can view a resource but aren't allowed to edit it, at which point 403 is correct. However if it's something owned by another tenant entirely, and is not public, then a 404 is correct.


No status code system is ever perfect or you wouldn’t get the benefit of the status codes. I feel like this problem is solved higher up by doing exactly what you say via OAuth, etc.


Might want to update the title to indicate that this is for the API.


Agree. The omission makes the title sound more sensational than it is. Token-only API authentication is not uncommon.


[flagged]


As username is public, it provides no security. So 1 account password with likely low entropy has been replaced with application-specific high-entropy passwords. This is an improvement.


Wouldn’t the low-entropy password still work on the web interface, and if so why is it an improvement? Any brute force attempts can very well be done on the web interface, and if there are countermeasures why can’t they be used on the API endpoints?


Isn't the idea you would have 2 factor auth on your account preventing any web brute force.

Then generate API keys on a per project reducing the attack surface in the case of breach?


Yes that’s correct, but if you choose to not use 2FA for whatever reason I don’t see why password auth shouldn’t be supported on the API instead of making you waste time generating an API key that won’t actually improve security in any way (since attackers can brute force the account anyway).


That's multiple plain text passwords, one for each use, with the ability to see when they have been last used and individually revoke them.


And more importantly, scopes, so that one token for posting gists can’t delete all your repos.


Unfortunately not, GitHub tokens are (outside of GitHub actions generated tokens) scoped for your entire account, which sucks. It should be an advantage though.


What are you talking about? Personal access tokens are scoped.


I had the same reaction then I re-read the comment and realized it was correct.

The granularity of Personal access tokens scopes is focused on what kind of actions you can perform on which kind of objects, but you cannot limit it to one single repository or to one single organization you belong.


The added security comes through how the new "plaintext password" is randomly generated (so you don't have to worry about users picking bad passwords).

~~Although it seems PATs are ~42 bits, which seems a little low~~


I didn't even know access tokens were a thing until just right now. In my reading about them, I found this, which has a screenshot, which suggests the token has ~40 hex digits. Assuming they're independent and random, that yields ~160 bits. Where are you seeing 42?

https://help.github.com/en/github/authenticating-to-github/c...


Wow, I completely messed up characters and bits.


HTTPS can use client certificates. While browser UI is not very nice for ordinary users, it seems like the best solution for API. I don't understand why isn't it used everywhere.


Because it is very complicated in both terms of UI and mechanics, and provides little to less additional security if you don't understand.

Just think of all the online sites that offer to verify or do something else that openssl can do if you paste your cert and private key. Most devs by now know not to do that with a password or API key, but it's the first thing people will do with private keys.


> Because it is very complicated in both terms of UI and mechanics

Yet every Github user is expected to generate a ssh keypair and copy/paste the public key when setting up the account.

> Most devs by now know not to do that with a password or API key, but it's the first thing people will do with private keys.

But they can handle submitting the ssh public key without any issue. Also, they most likely are not using online tools to generate their ssh key pair. I don't see why they would do that with openssl.


Easily revoked strong passwords that are less problematic to store on shared systems.


Thanks for comments !


Everything is getting more and more complicated for hobbyists over time. Mandatory HTTPS certs coming eventully, APIs forcing more convoluted authentication methods, GDPR compliance (probably going to scare away a lot of people from doing anything like writing a twitter clone hobby project, or even static sites where they might have to spend extra time configuring access logging) and other burdensome laws like the one from California, getting whined at if anyone catches a whiff you use passwords to log into SSH. So many barriers that less people are going to end up participating.


> APIs forcing more convoluted authentication methods

It's not really that convoluted: it's just setting a header with a fixed token, which is actually simpler than HTTP auth.


Slightly alarming that github has allowed username:password on api calls up to now- they have definitely kept quiet about it


Breaking apis, is breaking apis. Even for security reasons.

Removing something that works is not, in itself, "improving" security. It is breakage in the holy name of security.

If you have broken your system in the name of security it is not a more secure system. Its just a broken system that does not do its job. It might be "more secure" when users fix api usage, in the mean time its useless and is going to cost everyone time & money to fix.

It might makes more sense in the long run to move to something with a stable api.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: