Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ok, this feels like different advice, to me. It isn't to not use these, it is not to be the one implementing them? That is a lot easier to understand. I've been using AWS Cognito to get basic stuff up and running and it hasn't been too bad, I don't think. Have to convince people to not punch holes in things, but so far I have not been too turned off from things.


> It isn't to not use these, it is not to be the one implementing them?

More or less. The complexity comes from having to solve the edge cases, so it’s helpful to be one level of abstraction higher where your code is closer to your conceptual space.


My recent experience setting up AWS Cognito (not through Amplify) was pretty rough. I think vanilla Cognito doesn’t do a very good job of delivering you something that actually works out of the box with no footguns - you still have to handroll a lot of stuff.


On the AuthN side, it seems to be... fine? For AuthZ, things are not surprisingly outsourced heavily to the application side. I'm not clear on how I would want that to be any different, all told. Last thing I, personally, want to deal with is an annotation style setup to control who can do what. I am luckily working with something where we can have pretty easy definitions on who can do what.

I would love to hear more of the foot guns, though. Not trying to deny they exist.


> For AuthZ, things are not surprisingly outsourced heavily to the application side.

There's some newer startups working on extracting and centralizing AuthZ functionality. Ones I'm aware of:

* permit.io

* cerbos.dev

* Oso

I'm sure there are more.


I think this hits the same points I brought up in https://news.ycombinator.com/item?id=38873614. I do not claim that these should never be used. In fact, I would go farther and say in many cases this sort of thing should be used.


I think this is mostly my own ignorance and inexperience working with AuthN, but I had a harder time than expected just figuring out how to add basic log in and session management to my website. I spent a long time reading all the official Cognito docs getting nowhere. Eventually I started searching on the web and finally found two guides that actually managed to explain what I was looking for: [0], [1].

My philosophy toward authn right now is to never have to worry about security at all, so I want to completely minimize any personal responsibility towards managing passwords and tokens, first by outsourcing it as much as I can to products like Cognito, and failing that, by following best practices. My gripe with Cognito, as someone who doesn’t know much about auth and would prefer to learn as little as possible (I just want to add logins to my site!), is that it doesn’t give you an understandable API or user flow or best practices for implementing what I’d consider to be a “happy path” use case, unless you use Amplify. So if you’re someone like me who is learning as they go, there are tons of footguns and mistakes you can easily expose yourself to.

As an example: it’s not obvious that using their hosted UI with a redirect, for USER_SRP_AUTH, should point to a backend endpoint hosted/managed by you that converts access codes to tokens and performs a second redirect back to your actual site. You could easily do the wrong thing and redirect back to your main site with the access code still in the URL params, and then issue a call from the webclient that converts that code to tokens ( Which is terribly insecure as it opens up an exploit - user could share that URL with another not knowing that the access code in the url params is sensitive and could allow others to sign into their account). In fact, that entire exploit/antipattern was never even mentioned anywhere in any docs I found, but it would be extremely easy to accidentally introduce by naively using Cognito.

[0] https://aws.amazon.com/blogs/security/reduce-risk-by-impleme...

[1] https://dev.to/jinlianwang/user-authentication-through-autho...


I confess I am far less worried about access tokens leaking to end users than I probably should be. Assuming folks are validating their audiences on tokens, I don't see as much danger on the implicit workflow.

I'm also less clear on how the extra redirect there helps? If you are dependent on the user's client machine to follow the redirect anyway, they can still get middled, right? Compromised client doesn't follow the "code" redirect and instead directly calls to your oauth endpoint to get tokens. Since this is the "code" path, they can even get a session token that they can then start using on their own? Or do you lock down your oauth endpoints such that they can't be called? (Or is there more I'm mistakenly ignoring?)


The specific vulnerability I’m mentioning is if the user manually copies their post-redirect url (with access code in url params) and shares it with someone else. Specifically “hey check out this cool game!” (I’m making a game), sends a link, not knowing that nonsense after the site URL contains sensitive info that shouldn’t be shared. And then some savvy user, or bot, hijacks their account.

The extra redirect converts login.mainsite.url/?code=foo to mainsite.url with the code converted to tokens passed back via cookies. That way it’s much harder for a user to leak account details accidentally. In this auth flow, Cognito hands off the login by redirecting to foo.bar/?code=baz which could leak baz if baz gets shared.

My tokens’ cookies themselves are same-site only/https only and not directly accessible, so they’re protected against XSS AFAICT. AFAIK the only MITM security risk, once I got this working properly, is if something on the user’s network sniffs and leaks url params to my login endpoint (not sure if TLS makes this impossible by encrypting the url path, hope it does, but not something I can easily workaround anyway) or injects arbitrary code to my backend (in which case almost everything is compromised anyway).

I’m new to this auth stuff so I might be missing something, but I was surprised at the subtle security risk of Cognito’s default redirect behavior once I noticed it.


Ah, I think I see. The concern is the web app not clearing the access token from the URL that a user accidentally shares? That or maybe URL logs of where a user has accessed would leak an access_token?

This makes sense, and I think is compelling enough. The "code" is protected by some complicated effort in Cognito to make the code single use. (Right?)

Thinking of my hypothetical, I don't think there is any real protection from a compromised client. This is data that you want to give to the user, and you have to do that through the client. But the redirect has to be followed by the user's client, right?

To that end, you are probably still fine doing the code to token exchange using the web browser directly? Just not through the address bar, and instead with a post to the oauth endpoint. You can set the cookie locally, but no need to have another webpage involved.


I guess it depends on what you mean by a compromised client/ how it’s compromised. The auth flow is:

* mainsite.tld checks if user is unauthenticated/uses expired tokens. If so, redirect to Cognito UI hosted in a subdomain (auth.mainsite.tld) but managed by Cognito.

* Cognito UI prompts user for username/email and password. Potentially also MFA. Handles password reset. Eventually also handles signup.

* On successful sign in, Cognito redirects to my login endpoint with the access code in url params (login.mainsite.tld/?code=foo).

* My login endpoint extracts the access code, talks to Cognito again to confer it to tokens. Returns tokens via cookies in a response that redirects to my main site (mainsite.tld). (This is what prevents the user from accidentally sharing their access code in url params, manually copied out of their browser address bar, if I had instead done this in the browser).

* The main site now has working credentials; if the credentials go missing (because user cleared cookies) or expire (indicated in currently-unimplemented response when they interact with my authz/game server) they’ll be redirected back to the same Cognito UI.

I do not have control over how (url parameters) Cognito spits out the access code with this flow; still this flow is preferable to most others as at no point whatsoever am I responsible for managing user passwords, yet unlike a lot of new auth solutions that accomplish the same thing, users still actually have the option to sign in with passwords. What I do have control over is what redirects addresses are allowed out of Cognito, so afaict a compromised client (something bad that points to my login) can only redirect to my login endpoint which only redirects to my main site. There is no way to stop a compromised client (like a malicious browser and unsuspecting user) from doing bad things with the code or tokens but the same is true of anything entered into a browser ever, so that’s not a problem worth caring about.

But maybe I misunderstand (because I’m new to webdev too lol): what you’re suggesting in that last paragraph might be possible if I can reliably get the browser to hide the access code url param from the address bar/history. I just didn’t know how to do that from the browser without a redirect or reload. Even if that’s possible I’d still consider it a pretty glaring footgun, because while (hypothetically) possible it’s not necessarily obvious.


I think the catch there is that your "login endpoint" is still relying on the user's browser to get the code. The cognito endpoint returns a redirect to the user, and it is on them to follow it. So, the "code=foo" is visible to the user. If the user wants, they can try to prevent following the redirect and use that code directly.

That is, between each of your bullet points, there is a request by the user's browser. You do a request to the cognito hosted UI, it returns a code to the browser through a redirect to a webpage that is in it's "allowed list." The idea is that your "allowed list" includes a "login endpoint," but in all cases the code goes back to the user and it is on their browser to send that to the specified page.

I'm asserting that you can have javascript in the main web app that can use the "fetch" api in the browser to exchange a code for a token. That mostly hides it from accidental disclosure. And it makes it so that you don't have to have a special HTTP endpoint with another redirect in there setting cookies. (I'm assuming you'd set local storage or cookies with the fetch data.)

Right? Does that make sense?


Yes, the user can still share their access code if they really want to. That’s like them sharing their password.

What I’m trying to prevent, while adhering to general authN best practices, is a user accidentally or unknowingly sharing their access code because they copied the address in their browser bar/history and sent it to someone. If they jump through hoops to share it there is nothing I can do to stop it. But the default Cognito footgun I’m mentioning is that the code ends up in their browser window in a way that could be easily copy and pasted without them knowing why they shouldn’t do that.


Makes sense, I think.

I don't think you need another endpoint that will respond with cookie commands?

On your page, the one that got the "?code=foo" payload, you can use javascript on your site and make another call to the backend to get the tokens. The same javascript code should clear the URL so that a naive copy/paste doesn't get it.

This is in contrast to having another server side endpoint that can set cookies on another http redirect response to the user. One that has to be in the same domain as your application, for the cookie to set correctly.

This will leak the "code=foo" in any access logs surrounding the user. But, that is already in the user's history and already happened. Is why cognito goes out of their way to make "foo" one-time use.


The specific challenge with authz in the app layer is that different apps can have different access models with varying complexity, especially the more granular you get (e.g. implementing fine grained access to specific objects/resources - like Google Docs).

Personally, I think a rebac (relationship/graph based) approach works best for apps because permissions in applications are mostly relational and/or hierarchical (levels of groups). There are authz systems out there such as Warrant https://warrant.dev/ (I'm a founder) in which you can define a custom access model as a schema and enforce it in your app.


My concerns there are usually that data duplication for various reasons makes a ton of sense in an application. Replicating the permissions system throughout all of this duplication is usually tough, even if you do know the schema well.

Worse, though, often times applications are learning their schema as they go. This is the key benefit of "schemaless" approaches. Anything that adds friction to a schema in the system is likely to get shaken off due to slowing the teams down.

I do agree that resource approaches are the best. I try and boil it down to flat access lists for resources based on ID. Any application call that uses an ID gets checked against access lists for that ID.

I will fully grant that, if you are building a system where you do know the schema very well, then this changes.

Pulling this back to Open ID and friends, I am growing rather disillusioned with the "scope" tag on access_tokens to control this. I love the idea of being able to scope down access. I do not like the idea of leaning on that, too heavily.




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

Search: