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.
> 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.”
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.)
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.
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.
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.
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.
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?
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).
Unfortunately not, GitHub tokens are (outside of GitHub actions generated tokens) scoped for your entire account, which sucks. It should be an advantage though.
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 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.
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.
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.
- 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).