#dev 2021-06-09

2021-06-09 UTC
#
[KevinMarks]
ah o apparently not
#
[tantek]
[KevinMarks]++ keeping the vision of Yahoo pipes alive in the 2020s 😄
#
Loqi
[KevinMarks] has 13 karma in this channel over the last year (52 in all channels)
#
[KevinMarks]
twitter no longer has hcards for contacts, technorati no longer has the hcard to vcard converter, plaxo no longer converts vcards to portable contacts, and jsontoxoxo is now on unmung
[snarfed] joined the channel
#
[snarfed]
[jgmac1106] feel free to chime in on https://github.com/snarfed/granary/issues/137 !
#
Loqi
[snarfed] #137 RSS input
#
[jgmac1106]
[snarfed] were kinda my exact words after asking
#
[KevinMarks]
feedparser will do it
#
[KevinMarks]
it handles all kinds of gnarly feeds
#
[jgmac1106]
thread should take webmentions if folks want to chime in: https://micro.blog/DoctorMac/11554251
#
Loqi
[DoctorMac] @lukeboch and @manton I asked on indieweb chat. You could use unmung to turn the rss feed into an html feed and then granary.io to turn hfeed into json feed....I betchya results somewhere from broken to ugly but worth a shot
#
[jgmac1106]
ugg used the wrong browser to start, I handle multiple identities on microblog by using different browsers
#
[jgmac1106]
nobody in their right mind wants to read about NIST controls all day...been driving me crazy
#
[snarfed]
thanks [KevinMarks]! yup feedparser is legendary, it’d definitely be a solid choice for this
nertzy joined the channel
IWSlackGateway2, aaronpk, capjamesg and samwilson joined the channel
#
Zegnat
Hmm, did Slack cut that link up? Did not seem to translate well to IRC
hendursa1 joined the channel
#
sknebel
yeah, slacks link handling is borked
#
sknebel
has been for a while
#
Loqi
[Zegnat] #24 Shortened Slack URLs need to be expanded on IRC
hendursaga joined the channel
#
Saphire
Uh
#
Saphire
...what endpoints inideauth requires to implement o.o'
reed, calebjasik, Abhas[m], batkin[m] and nekr0z joined the channel
#
Zegnat
Saphire: sorry, how do you mean? There are two URLs that need to be discoverable for full IndieAuth: authorization endpoint and token endpoint
#
Saphire
...Authorization endpoint has to implement two different flows from what I understand?
#
Zegnat
Which two are you thinking of?
barnaby joined the channel
#
barnaby
Saphire: yes, that’s correct, as IA is defined right now, the authorization endpoint needs to implement both a user-facing authorization flow, and an app-facing auth code redeeming flow
#
barnaby
it adds some complexity as the user-facing stuff must be CSRF-protected, but not the app-facing stuff
#
barnaby
it’s a back-compat thing held over from older versions of indieauth, and is not compatible with OAuth2. there’s been some discussion about deprecating it, but for the moment it’s still part of the spec
#
Saphire
...I would really love for it to be split
#
Saphire
Because holy fuck trying to implement that in something that isn't PHP, Lua or other kind of dynamic language just kinda hurts
#
barnaby
well depending on your needs, you can choose to pre-emptively deprecate it yourself :) I don’t think there’s a list of which clients rely on that feature
#
barnaby
(I have a sneaking suspicion that the indieweb wiki might be one)
#
barnaby
fwiw I just mostly finished implementing it in heavily-type-annotated PHP, and it wasn’t too bad
#
barnaby
have a function which accepts an HTTP request object and returns an HTTP response. if the request is an auth code redeeming request, pass it off to the auth token redeeming logic. otherwise, pass it off to the authorization flow logic, wrapped in a CSRF middleware
tomlarkworthy joined the channel
#
tomlarkworthy
Serverless puppeteer in the browser for IndieWeb logins https://observablehq.com/@endpointservices/puppeteer Trying to help myself do e2e testing easier
#
tomlarkworthy
Would be interested if the demos work after someone logs in
#
tomlarkworthy
Though I realize I really need indieauth service accounts to automate e2e testing
#
Zegnat
Saphire: you might be able to chime in here, if you are having problems with implementation, that is a great reason to revive the discussion: https://github.com/indieweb/indieauth/issues/58
#
Loqi
[aaronpk] #58 Allow clients to always exchange authorization codes at the token endpoint
#
Zegnat
I am not sure about the “not compatible with OAuth2” though. Why do you think that, barnaby? That would be a great reason to deprecate it ASAP too. But as I understand it, OAuth2 does not specify any preferences as far as which endpoints do what, and it is completely fine even to have auth and token endpoint be the exact same URL always.
#
barnaby
oh okay, that might be me misunderstanding OAuth2 then
#
barnaby
I admit that I’ve not read the entire OAuth2 spec, but interpreted the first paragraph of that issue you linked as IA not being compatible/compliant/consistent due to a) allowing empty scope and b) allowing access tokens to be redeemed at the authorization endpoint
samwilson joined the channel
#
Zegnat
I am fully on board though, I actually think the spec as currently is also super confusing, cf. https://github.com/indieweb/indieauth/issues/62
#
barnaby
in other news, my WIP IA library’s auth endpoint has 92% code coverage!
#
Loqi
[Zegnat] #62 Clarification on issueing token with profile scope
#
Zegnat
Or well, not super confusing I was there for a lot of the spec writing talks, but maybe not super clear on the whole different-scopes-different-endpoints thing
#
Zegnat
Nice!
#
barnaby
heh yes I had my fair share of experiences with being confused about the spec
#
barnaby
definitely going to write an IA implementation guide once my library is in production
#
barnaby
something like the micropub implementation guide I wrote here https://indieweb.org/Micropub#Handling_a_micropub_request
#
Saphire
Zegnat: I'm having trouble trying to figure out just
#
Saphire
What set of queries I have to implement support for
#
Saphire
By wueries I mean like, list of "POST /auth, params blah blah to do this thing; POST there to do this"
#
Saphire
And uh..
#
Saphire
Why was that not deprecated when /token was added? >->
#
barnaby
I think the auth endpoint scopeless token redeeming was kept in a) for back-compatbility and b) because people wanting to have a server which just authenticates them, and doesn’t grant a token, is quite a common use-case
#
barnaby
say for example you have a personal site, want to be able to log in with it, but don’t have a micropub endpoint
#
barnaby
regarding the set of queries, let me stub a list on the wiki, as it’s all in my head right now anyway
#
barnaby
hmm where would be the best place to put this
#
barnaby
Saphire: have you seen https://indieweb.org/authorization-endpoint and https://indieweb.org/token-endpoint? they describe some of the flow, but admittedly not in the most implementation-focused way
#
Saphire
I have, but then I looked at the spec document and it describes the other workflow first?
#
barnaby
well, /token-endpoint is pretty good, but auth-endpoint glosses over some details
#
barnaby
so, the token_endpoint only has one flow, a POST request with authorization code details, which get verified. It returns a JSON response containing either access token details, or an error
#
Saphire
I see. That sounds simple enough
#
barnaby
the authorization_endpoint has three potential flows (per the current spec):
#
barnaby
a flow similar to the token_endpoint code redeeming flow, i.e. a POST request with auth code which results in a JSON response
#
barnaby
an authorization request flow, which is a GET request which the user was redirected to from their client app. the query string contains various parameters pertaining to the request. This flow needs to check that the user is logged in, redirect them to a login flow if not, and then finally return a consent/scope-granting form response on a logged-in request
#
barnaby
the final flow is a POST request containing the consent/scope-granting form submission, which needs to check validity, build an access_code and return a redirect back to the client app’s redirect_uri with code and state details
#
barnaby
(technically, the final flow could potentially be implemented at a different endpoint if you want, but I found it easiest to just re-use the authorization endpoint for it)
#
barnaby
the latter two flows MUST be CSRF-protected, the first flow cannot be
#
Saphire
Uh
#
Saphire
... Pretty sure CSRF does not quite work that- oh god
#
Saphire
Dynamically set header
#
Saphire
And other things.. god
#
barnaby
I don’t see what the issue is?
#
Saphire
But yeah I'm trying to implement it in a very type safe language. And it's very, very easy to make an endpoint that will take in a specific object constructed from params
#
Saphire
Except that.. in this case this object would be actually multiple ones blended together and the function would be a scary two/three way thing?
#
barnaby
ultimately the top-level endpoint code needs to accept some sort of HTTP Request object, and return an HTTP response
#
barnaby
and then within that, you detect the nature of the response, maybe build a query object from the HTTPRequest specific to the detected flow, and pass that off to a dedicated function
#
barnaby
I implemented it in PHP, but I didn’t use any dynamic features which aren’t available in, e.g. rust
#
barnaby
I do have one callback function which can choose to return either a pre-made HTTPResponse object or authentication data, but in rust I would just use an enum and it’d be totally type-safe
#
Saphire
It's less "impossible" and more "this gets ugly fast"
#
barnaby
yeah, there’s a fair amount of state to keep track of, and complications with handing a logged-out request off to a login route and then seamlessly restarting the indieauth request
#
barnaby
I spent a few hours reading the spec and scribbling diagrams on paper before I felt like I understood it well enough to start writing code
#
Saphire
Mood
#
barnaby
okay I documented the flows here, https://indieweb.org/authorization-endpoint#Flows — feel free to review for correctness and clarity Saphire, Zegnat, aaronpk et al
#
barnaby
also IMO there’s a bunch of stuff on that page which has little to do with the auth endpoint and needs to either be removed or clarified, e.g. the stuff about the sign-in form
#
barnaby
sure, that’s how a user gets to the auth endpoint, but it’s not part of the auth endpoint implementation
#
barnaby
now I have to go do some IRL work :P
#
capjamesg
Interesting wording by the BBC on the Fastly outage "blamed on a software bug."
#
capjamesg
"internet meltdown"
#
sknebel
some rumors they were rolling out code for Apple's new "VPN" and that broke
#
Zegnat
barnaby: I am not sure if I agree with "consent form submission" as a flow. That is an implementation detail, and is also why it is not included in the spec (or in any OAuth spec).
#
barnaby
Zegnat: sure, it’s not included in the spec, and that’s one of the reasons why the spec doesn’t work as an implementation guide
#
barnaby
there’s not much point having /authorization_endpoint just repeat what’s in the spec. IMO it’s better put to use as a practical implementation guide
#
mgdm
Apple's new VPN is Cloudflare, is it not?
#
Zegnat
The only two flows that MUST be supported are accepting a GET request that (in happy flow) results in a redirect back, and accepting a POST request that (in happy flow) results in a Profile URL Response
#
barnaby
yeah but in practise, an auth endpoint will most likely have an intermediary consent form
hendursa1 joined the channel
#
Zegnat
barnaby: I agree , for implementation guide. I just wanted to be a stickler and point out that there are really only 2 possible incoming requests that you MUST support for the spec. And those two can actually be split based on HTTP method already and you do not need to inspect parameters for it
#
sknebel
mgdm: both. and Akamai
#
barnaby
and the page as it was just glosses over how to deal with that
#
mgdm
ah
#
Zegnat
It is for instance completely fine (if it is easier for the implementation) to redirect the user to an entirely different endpoint for showing the consent form.
#
mgdm
Fastly's official line is "We experienced a global outage due to an undiscovered software bug that surfaced on June 8 when it was triggered by a valid customer configuration change."
#
barnaby
Zegnat, yeah, that’d be a good addition to the list of flows
#
Zegnat
So if, completely hypothetical because I do not know, Saphire’s problem is with inspecting query params, it is completely fine to skip that entirely. Check if the incoming request to the authorization endpoint is a GET or a POST, after that you know exactly what the possible set of parameters is.
#
barnaby
Zegnat: true, but only if your consent form submits a POST request to a separate endpoint
#
barnaby
I amended the intro paragraph
posdsoidosap joined the channel
#
Zegnat
The consent form could be fully JS based for all I know, and talk with an endpoint on an entire different domain. That is why I do not like to generalise about it, and is why OAuth makes it an implementation detai
#
posdsoidosap
!mf2 https://example.com
#
barnaby
also, while it is in theory currently possible to determine which flow is happening based on the method, in practise it’s also necessary to inspect the query params (response_type=code, specifically)
#
Zegnat
? Not really? If you are doing a GET, you can assume that response_type=code is set. In fact, you should immediately stop the process if it is not.
#
Saphire
Zegnat: so authenticated vs non-authenticated..
#
Saphire
Former has a `code` query param, the other doesn't?
#
barnaby
exactly, you need to check the response_type parameter to make sure it’s a valid request
#
Zegnat
So you can make the call based on HTTP method, if it is a GET, you probably want to validate the params so you can exit early if it is not a valid OAuth request, but at that point you have already determined the type of request based on the method. (Which I thought the issue here was.)
#
Saphire
Or wait, was that an implementation detail
#
Saphire
Authenticated /on the auth endpoint end/, or on client end?
#
barnaby
ah okay, yeah that’s true
#
Zegnat
When a client makes a GET request against the authorization endpoint, it expects to be redirected back to a URL it provided in that GET request. Any pages (or none) you chose to show in between is up to you.
#
Zegnat
When a client makes a POST request against the authorization endpoint, it expects a Profile URL response per the spec back.
#
Zegnat
Those are the only two MUST cases for an authorization endpoint.
#
barnaby
yep, which is described well by the spec, but at /authorization-endpoint I want to help people actually build practical endpoints, which involves some non-generic implementation details
#
barnaby
details which, per my and Saphire’s experiences, are not currently well described anywhere easily discoverable
#
Zegnat
Yeah, I can see how that is not really clear everywhere. I guess I am just a stickler on the fact that none of those details should be covered by the IndieAuth spec (wich is an extension to OAuth 2.0) because it can and will vary wildly between platforms.
#
Saphire
Oh
#
Saphire
...the nodejs example is uh
#
barnaby
but I agree that it’s worth explicitly mentioning that they are implementation-specific suggestions rather than spec requirements
#
Saphire
Actually the best explaination so far
#
Saphire
>->
#
capjamesg
sknebel interesting re: rumors of VPN. It makes total sense for Apple given their privacy commitments.
#
Zegnat
Although it is a bit old, there is also the PHP one in ~400 lines, Saphire: https://github.com/Inklings-io/selfauth/blob/master/index.php
#
Saphire
This is actually pretty helpful
#
Zegnat
That kinda does what I described, in that the first check it does after defining some util functions, is to see if the current request is a POST with a code param: https://github.com/Inklings-io/selfauth/blob/a76ca38d2d4a8b19f98fe85c8b8d4301f21be3bc/index.php#L163
gRegor joined the channel
#
Zegnat
I think that node one is based on the PHP selfauth one. It uses the exact same logic for checking state values, with the exact same function names, haha
#
barnaby
yeah it’s a nice readable minimal example
#
Zegnat
I wonder why it does that. It is not good code. We used md5 as a lowest common denominator for old PHP versions. Node.js should have been able to do better
#
Zegnat
Or well, the code is fine, but it is far from as secure as can be
#
Saphire
Yeah
#
Saphire
And uh
#
barnaby
yeah, funny that they use md5 after having used sha256 a few lines earlier
#
Saphire
That P something standard
#
barnaby
that’s the danger of writing for the lowest common denominator — other people might take it as a reference implementation ;)
#
Zegnat
barnaby: PHP one does that too. But that might have been because the signed codes part that adds time-to-live was added later and we did not want to break existing setups with md5 passwords.
#
Zegnat
selfauth has done pretty well as a reference implementation for people, I believe. And most of the error checking is super solid. But for the actual hashing stuff it is showing its age
#
barnaby
what’s response_type=id?
#
Zegnat
Deprecated
#
Zegnat
It was how you previously communicated if you wanted a token or just wanted identification
#
barnaby
that’d explain why it’s not in the spec
#
barnaby
got it
#
Zegnat
The part that there were 2 different flows for authentication and authorization is why we are stuck with authorization endpoint having to handle code exchanges
#
Zegnat
My current implementation is more comments than code, hahaha
#
Loqi
nice
#
Zegnat
https://github.com/Zegnat/php-mindee/blob/development/index.php - for an old version. Almost all code blocks have an @see with spec links
#
Zegnat
s/code/comment/
#
barnaby
oh that’s good reference for validating the request params, I hadn’t gotten very far with that yet
#
barnaby
thanks for the various @see links, that’ll limit how much time I have to spend digging around in the OAuth2 spec(s) themselves
#
Zegnat
Mindee is replacing selfauth for me, and with the risk of ending up as some sort of reference implementation again I wanted to do it right :P
#
barnaby
heh I’m in the same position, writing a new IA server library to replace my old one and hopefully fix most of the problems with it
#
Zegnat
There is also https://github.com/Zegnat/php-mintoken with some more thoughts on what makes a good token in https://github.com/Zegnat/php-mintoken/wiki/Token-design if you want to see my take on the token part of the spec
#
Loqi
[Zegnat] php-mintoken: A minimal IndieAuth compatible Token Endpoint.
#
Zegnat
Note that it is an implementation of an older spec version though. As it needs to be able to contact the authorization endpoint to see if a token should be issued
#
barnaby
"sqlite3 tokens.db < schema.sql" < now that’s a dbadmin approach I can live with ;)
#
Zegnat
I could do a whole script for initialising a database and prepping the tables … oooor I can just ask people to run that :D
#
sknebel
we probably should update selfauth to match what currently supported PHP versions can do
#
sknebel
7.x brought a bunch of niceties there
#
barnaby
at least putting the back-compat stuff behind function_exists calls for newer ones might be a good idea, if you didn’t already
#
Zegnat
I think we did that in some places
#
Saphire
So for security uh. I should only let the GET /auth_endpoint to only redirect to actual page, one which is set to Allow-Origin only of the auth site?
#
barnaby
but if md5 is just there to support existing hashed passwords then I guess that doesn’t apply
#
Zegnat
But only for newer features, as older features were jsut not touched anymore, haha.
#
Saphire
And have a token supplied to that page that can be verified later?
#
Saphire
On submission of consent
#
Zegnat
Saphire: I am not sure I follow. On submission of consent is when you would generate a code and redirect to user back to the original client.
#
Saphire
So it goes.. client -> /auth_endpoint with query of {me, redirect_url, client_id, ...}, Then auth endpoint does a redirect or in any other way goes through an authentication and authorization flow, the entire flow resulting (on success) in redirect to redirect_url and query params of code and state, where state is original state supplied to endpoint and code is an opaque token that can be
#
Saphire
verified later?
#
barnaby
yep, exactly
#
barnaby
and the opaque token can be exchanged either for profile information (at the auth endpoint) or an access token (at the token endpoint)
#
Saphire
...and a separate flow of {code, redirect_url, client_id} to same endpoint where it checks the token (in opaque way) and just goes nah, or ok and gives user info?
#
Saphire
*flow of POST {...} to same
#
Zegnat
POST {grant_type, code, client_id, redirect_uri, code_verifier}
#
Saphire
Oh, right
#
Zegnat
If this POST went to the authorization endpoint it will result in either HTTP 200 response with a JSON body { me[, profile] } or HTTP 400 with a JSON body according to OAuth rfc 6749 with error information
#
capjamesg
16:07 to 18:29 very interesting roundup of Apple's WWDC privacy announcements.
#
capjamesg
Seeing this makes me want to get back further into the Apple ecosystem.
#
Saphire
And both POST /auth_endpoint and POST /token_endpoint "may" check for code_verifier?
#
Saphire
...can I embed the original code_challenge in the token?
#
Saphire
(assuming the token is properly MAC protected)
#
Saphire
Oh hey look, a youtube video with some... "Aaron". Wonder who that is :P
#
Saphire
RIGHT
#
Zegnat
code_verifier is PKCE, an extra security measure of OAuth
#
Saphire
"The server MUST NOT include the "code_challenge" value in client requests in a form that other entities can extract"
#
Zegnat
If it is given, you should probably make it a "must" to check
#
Saphire
Aka don't store it in base64 encoded token with a signature v:
#
Zegnat
Ah, yeah, definitely not :P
#
Saphire
Darn, there goes THAT easy way out
#
Saphire
...I guess a hash of that stored in same plain-text token uh, also is not the way to do it?
#
barnaby
where is that quote from Saphire?
#
barnaby
hmm okay I need to figure out if that will cause problems for my implementation
#
barnaby
hopefully “client requests” only refers to requests sent to/redirected to the client app
#
barnaby
hopefully “client requests” only refers to requests sent to/redirected to the client app
#
Zegnat
I am not sure I follow. Sorry. Some of this stuff might just be super obvious to me because I have been involved from the get go :P
#
Zegnat
code_verifier is only sent once, by the client, when they go and exchange the code for a token (or for profile information).
#
Zegnat
Clients have to keep it an absolute secret until that point.
#
Zegnat
For stateless clients, you can store it inside the "state" value, but in that case have to make sure it cannot be extracted from it, e.g. by encrypting the state payload
#
Zegnat
Does that make sense?
#
barnaby
so, my server library currently includes an unencrypted form of the code_challenge in any intermediate requests during the authentication and consent screen flow
#
barnaby
but I can’t tell if they would fall under the “client requests” which are prohibited from including the code_challege by https://datatracker.ietf.org/doc/html/rfc7636#section-4.4
#
Zegnat
That is fine, code_challenge is “public”
#
barnaby
not according to the quote Saphire found
#
barnaby
The server MUST NOT include the "code_challenge" value in client requests in a form that other entities can extract.”
#
barnaby
unless I’m misunderstanding exactly what’s going on there?
#
Zegnat
Oh, hmm, that one is weird
#
barnaby
yeah, what’s a “client request”, and why must the challenge be kept secret?
#
barnaby
there are some errata associated with that document but I can’t find any related to that specific sentence https://www.rfc-editor.org/errata_search.php?rfc=7636&rec_status=0
#
Zegnat
Maybe "client request" there means the redirect back to the client
#
barnaby
hopefully!
#
aaronpk
I think that text is there because of code_challenge_method=plain
#
barnaby
that would make the most sense
#
Zegnat
aaronpk: ah, yeah, that too
#
barnaby
aaah I keep forgetting that the plain challenge method exists
#
barnaby
good point aaronpk
#
Zegnat
But it should be fine to communicate it to yourself in URLs.
#
barnaby
it wouldn’t be too much work to rework it, but I was happy with it the way it was :D
#
Zegnat
They probably mean that you should not put the challenge next to the code, as the point of the challenge is that only the original requestee knows which code goes with which challenge and you want to keep it that way
#
aaronpk
and also from earlier, I am all in favor of making the wiki pages more of an implementation guide, calling out things that aren't appropriate to put in the actual spec. but it would also be useful to highlight that those things are still implementation details
#
barnaby
agreed, I tried to amend my flow descriptions to add that
#
barnaby
maybe have a “strict flows according to the spec”, and “practical suggestions for flows including authentication and consent screen details”
#
barnaby
so that there’s a summary of both on the same page, and so that there’s a structure for adding alternative implementation-specific flow suggestions which still comply with the general spec flow
#
Saphire
Strict flow according to spec leaves a lot of areas "up to implementer's imagination" basically v:
chenghiz_ joined the channel
#
Zegnat
That is because the spec is there to normalise the traffic between the client and the server. Not the client or the server internals.
#
Zegnat
Just when servers are on the web, and the front-facing part of authentication and consent screen are handled by them, it starts to blur the lines a little, as the majority of the people implementing the server side of the spec will also need to implement all those unspeced things
#
barnaby
yeah, I ended up thinking of the spec as being written from the client’s point of view
[Murray] joined the channel
#
Zegnat
That might be a more illustrative way of thinking, yes. It is definitely laid out that way. Though you can read it as the server’s point of view by treating the spec as being “in the likely order of requests send to me by a client”
#
Saphire
I kinda need to get indieauth working on my site to get to wiki, oooor remove the <link>s for indieauth leading to nothing. Actually invalid nothing, even
#
barnaby
bootstrapping that is what https://indielogin.com/ is for!
#
Saphire
But that means I'll need to remove that header! :C
#
Saphire
*link
#
Saphire
Sooo, this still means no storing code_challenge in the token
#
Saphire
Unless token is encrypted in a way that only l- no no, that's just begging to chosen plaintext attack unless it's using per-token key which uh
#
barnaby
not in an unencrypted form, at least. but why do you want to? the client app shouldn’t need a copy of code_challenge
#
Saphire
...which is still back to same solution as storing code_challenge away - aka storing SOME piece of info in the DB, even if it's temporary
#
Saphire
barnaby: trying to find a way to hide from needing to keep a database of tokens' code_challenges
#
sknebel
if you have given out the token, you're done, you dont need it anymore
#
barnaby
oh you mean storing it on the server side so the server can check exchange requests later, okay
#
Saphire
sknebel: PKCE though?
#
Saphire
That requires at least storing a code_challenge until the token is used up
#
Saphire
...uh
#
barnaby
in that case, having the access code be an encrypted structure containing data about itself should be fine, no?
#
sknebel
you mean the authorization_code, not otken?
#
barnaby
what do you mean by “chosen plaintext attack”?
#
Saphire
OH
#
Saphire
oh derp
#
Saphire
Right I kept thinking of authorization code from authorization_endpoint as like, THE token or something >.>
#
barnaby
nope, it’s a temporary one which is only used once to exchange for either profile information or an access_code
#
barnaby
the access_code is the one which can be longer-lasting
#
barnaby
access_token, sorry
#
Saphire
I am assuming that authorization_endpoint returned code is basically just a temporary opaque thing (that is sufficiently non-predictable to not let people guess it!) that only lives for like, a minute or something?
#
Saphire
Well, 5 minutes, idk
#
barnaby
yep, exactly
#
Saphire
...and while it CAN be implemented basically through same stuff as a full token, you also can uh
#
Saphire
Just have a small runtime-only storage for those and clear it out from old stuff every so often?
#
barnaby
and according to the spec it MUST only be usable once, which means you either have to persist them somewhere and delete/expire them after they’re exchanged, OR keep track of which ones have been exchanged in your list of access tokens and check against that
jeremycherfas joined the channel
#
Saphire
Aka do not do it completely stateless
#
barnaby
yes, sadly
#
Saphire
(as to not let your generous timeout of 5 minutes to let someone do hundreds of tokens for someone's account)
#
Saphire
Buuut you can have a small vector/table/object/etc in your persistently running server app (unless you are on something more per-request like PHP where you'll need to use a DB or other value store) that would be cleaned out from say, entries older than 5 minutes
#
Saphire
And only give tokens out for codes that are in that storage?
#
barnaby
yep, that sounds like a good approach
#
Saphire
(obviously store the challenge next to the codes, IF challenge is available)
#
Saphire
...I guess internally just have ChallengeType None v:
#
Zegnat
I think that is something like how I do it, I would have to double check. I actually store the one-time opaque codes in the db, and have all the important client details associated with it.
#
Zegnat
When the client then comes to exchange the code for a token, that token is added to the same database record, turning the code storage into a token storage. Codes are automatically one-time-use, because on second try I see the token field is already filled.
#
Zegnat
It also makes it so all the client information that I got when the code is first requested is automatically associated with the issued token.
#
Zegnat
One single db then gives me full tracing: when was a code created, when was it exchanged for a token (if at all), which client did it …
#
Zegnat
The stateless way is what the previously linked endpoints do, where they put all that information into the code itself encoded/signed/encrypted in some way. Which is also fine, but I found that to be more overhead in the longrun than depending on an SQLite file
#
barnaby
and then you periodically purge expired records which never got exchanged for an access_token?
hendursaga joined the channel
#
barnaby
the stateless approach is nice but it doesn’t strictly comply with the requirement that access tokens must be only redeemable once, right?
#
barnaby
*auth codes, sorry
[snarfed] joined the channel
#
Zegnat
Well, if both your codes and your tokens are stateless.
#
barnaby
yeah, exactly. at least one of them has to be stateful
#
Zegnat
If you only want the codes to be stateless, but tokens are actually stored, you can always store the code on token generation
#
Zegnat
I think some applications just bite the bullet on that if they must be stateless. So they set a short TTL on the code and assume that to be reliable enough *shrug*
#
barnaby
yeah IMO it’s not necessary to comply strictly for most people, if the TTLs are small enough
#
barnaby
but when making a library I want to ensure that at least defaults to strict spec-compliance
#
Saphire
Hm
#
Saphire
Would something like a snowflake with a small bit of randomness be sufficiently secure for a code?
#
Loqi
[ulid] spec: The canonical spec for ulid
#
Saphire
...can you reuse the auth code as part of info within a token?
#
Zegnat
As long as the code can only have been generated by you (because it ensures the user has consented) it can be anything. Randomness is not a concern.
#
Saphire
(given that the code was already used up)
#
Zegnat
Same goes for the token, you can put anything into the token as long as it cannot be forged
#
Saphire
So it could be just a timestamp signed with private key, etc?
#
sknebel
my tokens are literally just random values
barnaby1, jjuran_ and wagle joined the channel
#
Saphire
Hm
#
Saphire
... Is there any reason to keep- okay nvm yeah
#
Saphire
Hm
#
Saphire
Was saying, any reason to have stateless tokens (as in, MAC-ed tokens with some of the original info in them) at all?
#
Saphire
You'll still have to check that they are not revoked
#
Saphire
...hm
#
Zegnat
If you are not being stateless, as sknebel said, you can literally just make it 100% random bytes
#
sknebel
right. with stateless you ahve the revocation issu
#
sknebel
wow, can't type today
#
Saphire
Yeah
#
Saphire
So stateless is more "don't have to check the db for everything"
#
sknebel
right.
#
Saphire
But you.. still have to check at least for the token being valid
#
sknebel
right. which is why I think for personal sites it doesn't matter
#
Saphire
At which point properly secure stateless token ends up being just plain db optimization at most
#
sknebel
for large systems there is some argument that it might be easier to keep and check a small revocation list on each node than always querying a DB of all tokens
#
sknebel
(stateless can still revoke *all* tokens by rotating the signing key)
#
sknebel
but for what I'm doing I dont care about the small cost of a lookup
#
Zegnat
Stateless always sounds fun when it is described as “look mum, no datatabase”, but then when you actually start implementing a full authorization flow and find out you need to bring in encryption to hide things from clients, keep track of ttls, etc., it is no longer as fun ;)
#
sknebel
I do "look mum, no database, just file system" :P
#
Saphire
And then you ask yourself "how do I keep tokens that are leaked from being abused?"
#
Saphire
And realize the entire damn thing is silly because you still end up tracking everything
#
Saphire
Heh
#
Saphire
> Using a common data format allows for easy interoperability with established solutions. It is perfectly fine to develop your own token solution (as long as you don’t roll your own crypto). However, JWTs are the established solution, and you can’t go wrong with them.
#
Saphire
...sure
#
Zegnat
Hehe, no, for the leaks you realise as we discussed a day or two ago here, that it would be great if even the tokens are short lived.
#
Zegnat
And instead you also give out refresh tokens, so shortlived tokens can be requested when one elapses.
#
Zegnat
And then you have to implement the refresh flow :P
#
Saphire
Do apps refresh tolens automatically?
#
Zegnat
I do not know of any IndieAuth clients that handle refresh tokens, no
#
Saphire
Hmm
#
Saphire
Wonder what are the statistics for the auth on indieweb?
#
Zegnat
Specifically on indieweb.org ? aaronpk might have those. Or maybe not. We are pretty statistics-lite in general on IndieWeb things. Wouldn’t want to do too much tracking
#
Saphire
Mmh
#
Saphire
Was thinking in general? Dunno
#
Saphire
Like, how many people are using the indieauth service vs having their own endpoint
IWSlackGateway and [tantek] joined the channel
#
[tantek]
hey snarfed, does granary support consuming h-feed h-entry u-featured images and converting them to some equivalent in Atom? That is, how do you publish featured images in Atom? perhaps <entry><link rel="featured" href="image.jpg" /> ?
#
[tantek]
what is featured
#
Loqi
featured is a proposed mf2 property (typically as u-featured) for h-entry that indicates a representative image for a post https://indieweb.org/featured
#
[tantek]
somewhat related, are folks using any kind of markup to express their "related posts" or "related articles" that they link to from a specific article/post?
shoesNsocks joined the channel
#
[tantek]
e.g. the "obvious" "simple" thing in plain HTML would be rel="related", but I'm not sure that's the best for structure inside an h-entry. I could see a u-related-entry property, but wanted to first check to see what people's existing publishing did.
#
[tantek]
or if other formats have something already, e.g. does Atom have a notion of <link rel="related" href="article.html" /> that you could put inside an <entry> ?
#
[tantek]
reading 4287 (again).
#
[tantek]
it's too bad the atom:icon element is only specified as a child of <feed>, missed opportunity there to re-use that for <entry> as a way to do a featured/preview image for an entry
[Murray], shoesNsocks and [snarfed] joined the channel
#
[snarfed]
[tantek] yes! granary supports u-featured. doesn’t do anything special though, just includes them as picture attachments along with u-photos
#
[snarfed]
in Atom, they end up both as enclosures and rendered HTML in the content
#
[tantek]
snarfed, would it be worth exploring <link rel="featured"> in Atom? or not enough other consuming code to care?
#
[tantek]
something to distinguish from other enclosures
#
[tantek]
including other photos
#
[tantek]
also curious about your thoughts about marking up "related posts" per above ^
gRegor joined the channel
#
[snarfed]
sure! I’m open to all of those. I don’t really follow a lot of markup semantics like those, so I’m probably not the best person to lead any changes, but I’m happy to review and merge!
[schmarty] and [KevinMarks] joined the channel
#
[KevinMarks]
mastodon's Atom feeds had a bunch of extra namespace stuff from PoCo to do author iirc
barnaby joined the channel
#
[KevinMarks]
though they dropped Atom and now have less expressive RSS
alex11 joined the channel
#
[tantek]
[KevinMarks] speaking of Author in Atom, do you know any Atom feeds that publish author & publisher info in their markup?
#
[KevinMarks]
try newspaper sites
KartikPrabhu and [aciccarello] joined the channel
#
[tantek]
barnaby yours does not have a separate publisher from the author
#
barnaby
ah sorry, misunderstood the question
#
[tantek]
"author & publisher info" 🙂
#
[tantek]
Atom seems to lack something for publisher explicitly
[Ana_Rodrigues] joined the channel
#
[tantek]
closest hack might be to use atom:contributor element, with a uri, and then if that uri prefix matches the permalink of the entry, then that contributor can be determined to be the "publisher"
#
barnaby
is this theoretical, or do you have an atom feed where you want to provide separate publisher and author info?
#
[tantek]
[KevinMarks] newspaper sites predate Atom. I'm kinda shocked this is not explicitly designed in Atom, or be documented as a practice
#
[KevinMarks]
hm, checking uk ones and they're using rss and dc
#
[tantek]
ugh the semantically vague & useless d
#
[tantek]
I tried googling for:
#
[tantek]
how to markup the author and publisher of an atom feed
#
[tantek]
and first result is a very useless page on Google 🙄
#
[tantek]
this is one of the worst dev docs pages I have seen on Google: https://support.google.com/news/publisher-center/answer/9545420?hl=en
#
barnaby
“Avoid the use of smart quotes.”?!
#
[tantek]
presumably in the markup
#
[tantek]
(I hope)
#
barnaby
smart quotes as in curly ones? “”?
#
[tantek]
the atom feed example both violates dry (duplicates author info for no reason), and uses CDATA for content 🙄
#
[tantek]
barnaby haha yes. they're not very smart
#
barnaby
trained himself to type in curly quotes years ago and isn’t about to stop for google’s sake
#
[tantek]
I mean don't use them for attribute values
#
[tantek]
that's the point I'm pretty sure
#
barnaby
well yeah, that isn’t going to go very well
#
[tantek]
actually "avoid" is the wrong guidance. it should be "Do not use smart quotes for attribute values because they will fail."
#
barnaby
it just says to avoid them, without any further explanation :/
#
barnaby
yeah exactly
#
[tantek]
yeah, or rather “curly quotes”
#
barnaby
I wonder if that’s based on actual issues people have had
#
barnaby
there are various text processors which will try to add curly quotes, e.g. some versions of markdown IIRC
#
[tantek]
yes because text editors "helpfully" turn your normal quotes into curly quotes, thus ruining your markup
#
barnaby
that’s why I learned to type them myself, and then turned off auto-curling wherever I could
#
barnaby
[tantek]: re “uses CDATA for content 🙄”, what’s wrong with that if you’re publishing HTML content which would result in invalid XML if included directly in the ATOM feed? e.g. valid HTML5 void elements like <br> or <img>?
#
[tantek]
if you can generate valid Atom/XML, you can generate valid XHTML5 for embedding in valid Atom/XML
KartikPrabhu and capjamesg joined the channel
#
[snarfed]
in some cases yes, but not always easily. eg granary uses CDATA because it sometimes has to to pass through arbitrary input HTML content, and I don’t really want to try to parse that, regenerate it as XHTML5, and handle the 50 resulting cases of lossiness and other bugs that would happen
#
barnaby
[snarfed]: do you search the 3rd party content for CDATA closing tags? what would happen if some of the arbitrary HTML content included one and prematurely ended the CDATA section?
#
[snarfed]
🙉 🙉 🙉
#
barnaby
I suppose the only guaranteed-non-fragile method would be to escape all the HTML-relevant characters in the 3rd party content, and then include it in the ATOM without CDATA
#
barnaby
then it’s just a safe blob of text which is guaranteed to not mess with the surrounding ATOM, and will be parsed to the original content by consumers
#
[tantek]
escaped HTML? sounds like RSS embedding techniques
shoesNsocks joined the channel
#
@ChrisAldrich
↩️ I’m happy to help you try to put together an IndieWeb-friendly version w/ Webmentions which work w/ multiple platforms including WordPress, Known, Grav, &c. You might find some examples & pieces on IndieWeb wiki, particularly their Education page. cont'd https://boffosocko.com/2021/06/09/55792003/
(twitter.com/_/status/1402698781750022148)
[jacky], [Will_Monroe], mikeputnam, Kaja, Zegnat, [chrisaldrich], chrisaldrich, gRegor and [manton] joined the channel
#
[manton]
[aaronpk] Just in case you didn’t notice it, Apple had a session on WebAuthn this week. I skimmed through the first half, so not sure it’s relevant to anything IndieAuth-related yet. There’s also this blog post summary: https://sixcolors.com/post/2021/06/wwdc-2021-apple-takes-the-first-steps-to-a-password-less-future/
#
aaronpk
thanks! i'm going to have to take a look at that in more detail
[chrisaldrich] and gRegorLove_ joined the channel