HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
jrockway
jsso2
Go2020–2022
jrockway / jsso2

jsso2

Self-hosted passwordless single signon.

2Distinct people
10Mentions
0Explicit recommenders
34GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Self-hosted passwordless single signon.

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by month10 dated mentions

Observed mentions: 2020-10-30 21:10:32 UTC to 2022-11-20 10:19:45 UTC.

012020-10-01 00:00:00 UTC to 2020-11-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 commentsOct 20202020-11-01 00:00:00 UTC to 2020-12-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2020-12-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2021-01-01 00:00:00 UTC to 2021-02-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2021-02-01 00:00:00 UTC to 2021-03-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-03-01 00:00:00 UTC to 2021-04-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2021-04-01 00:00:00 UTC to 2021-05-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2021-05-01 00:00:00 UTC to 2021-06-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-06-01 00:00:00 UTC to 2021-07-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-07-01 00:00:00 UTC to 2021-08-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2021-08-01 00:00:00 UTC to 2021-09-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-09-01 00:00:00 UTC to 2021-10-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-10-01 00:00:00 UTC to 2021-11-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 commentsOct 20212021-11-01 00:00:00 UTC to 2021-12-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-12-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-01-01 00:00:00 UTC to 2022-02-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-02-01 00:00:00 UTC to 2022-03-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-03-01 00:00:00 UTC to 2022-04-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2022-04-01 00:00:00 UTC to 2022-05-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2022-05-01 00:00:00 UTC to 2022-06-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-06-01 00:00:00 UTC to 2022-07-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-07-01 00:00:00 UTC to 2022-08-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-08-01 00:00:00 UTC to 2022-09-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-09-01 00:00:00 UTC to 2022-10-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-10-01 00:00:00 UTC to 2022-11-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2022-11-01 00:00:00 UTC to 2022-12-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 commentsNov 2022

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
Oct 20202020-10-01 00:00:00 UTC2020-11-01 00:00:00 UTC101
Nov 20202020-11-01 00:00:00 UTC2020-12-01 00:00:00 UTC101
Dec 20202020-12-01 00:00:00 UTC2021-01-01 00:00:00 UTC101
Jan 20212021-01-01 00:00:00 UTC2021-02-01 00:00:00 UTC101
Feb 20212021-02-01 00:00:00 UTC2021-03-01 00:00:00 UTC000
Mar 20212021-03-01 00:00:00 UTC2021-04-01 00:00:00 UTC101
Apr 20212021-04-01 00:00:00 UTC2021-05-01 00:00:00 UTC101
May 20212021-05-01 00:00:00 UTC2021-06-01 00:00:00 UTC000
Jun 20212021-06-01 00:00:00 UTC2021-07-01 00:00:00 UTC000
Jul 20212021-07-01 00:00:00 UTC2021-08-01 00:00:00 UTC101
Aug 20212021-08-01 00:00:00 UTC2021-09-01 00:00:00 UTC000
Sep 20212021-09-01 00:00:00 UTC2021-10-01 00:00:00 UTC000
Oct 20212021-10-01 00:00:00 UTC2021-11-01 00:00:00 UTC000
Nov 20212021-11-01 00:00:00 UTC2021-12-01 00:00:00 UTC000
Dec 20212021-12-01 00:00:00 UTC2022-01-01 00:00:00 UTC000
Jan 20222022-01-01 00:00:00 UTC2022-02-01 00:00:00 UTC000
Feb 20222022-02-01 00:00:00 UTC2022-03-01 00:00:00 UTC000
Mar 20222022-03-01 00:00:00 UTC2022-04-01 00:00:00 UTC101
Apr 20222022-04-01 00:00:00 UTC2022-05-01 00:00:00 UTC101
May 20222022-05-01 00:00:00 UTC2022-06-01 00:00:00 UTC000
Jun 20222022-06-01 00:00:00 UTC2022-07-01 00:00:00 UTC000
Jul 20222022-07-01 00:00:00 UTC2022-08-01 00:00:00 UTC000
Aug 20222022-08-01 00:00:00 UTC2022-09-01 00:00:00 UTC000
Sep 20222022-09-01 00:00:00 UTC2022-10-01 00:00:00 UTC000
Oct 20222022-10-01 00:00:00 UTC2022-11-01 00:00:00 UTC000
Nov 20222022-11-01 00:00:00 UTC2022-12-01 00:00:00 UTC101

What Hacker News says

10 sources
Sure, if you want to compose the various methods into a single transaction, then each business-logic-implementing function needs to take a transaction object as a parameter. In that case, you don't even need something like DBImpl. Looking at database code I have written, I never do the object thing (but was replying to an author who does). I typically have a package with functions that take transactions as an argument, like this: https://github.com/jrockway/jsso2/blob/master/pkg/store/sess... (If you poke around the package, methods that don't make more than one database call take a sqlx.ExtContext instead of a *sqlx.Tx. Functions that need to start their own transactions take the connection instead, though I'm not sure I'd recommend that approach because it hurts composability.) To test it, I just run against an actual Postgres instan
Read the rest
ce which is pretty easy to find. (I am not sure I would steal my database setup / teardown utilities from that project. The tests end up indented too far. A more idiomatic Go way is "app := testapp.New(); defer app.Cleanup(); tests go here"; in that codebase I picked the "testapp.Test(t, func(t testing.TB) { tests go here })" pattern. Definitely something I look for and avoid these days, but didn't in 2020 ;)
In Go Style
That's weird. I implemented it a year ago and it basically works perfectly on all the browsers I use. I can enroll a Yubikey on my desktop, and then hold it up to my iPhone to log in. (Of course, I also enrolled FaceID on the phone.) My one complaint is that enrollments don't sync between my iPhone and my iPad. Had to enroll my face twice. Code is here: https://github.com/jrockway/jsso2 (not security reviewed or well documented)
In WebAuthn Browser Support
I went this route. I really like the design of Google's Identity-Aware Proxy. You host your apps behind it, the proxy authenticates users and passes a JWT to the application that contains additional metadata. The app can choose to care or not care about the JWT. This is nice for read-only things that aren't particularly important (something like jaeger-ui). Or the app can choose to care, and do one cryptographic operation to get a trustworthy username and group membership list. This is so much easier from an operations and implementation perspective than integrating something like OIDC. I wish more applications supported this, and didn't force me to hack OIDC into this flow. As for WebAuthn, yes, that's what you should be using these days. People are terrible at choosing passwords, so why make them? I wrote an authenticating proxy
Read the rest
that maintains username -> WebAuthn credentials, and use it for my personal projects. I wouldn't recommend that someone else use it (incomplete featureset, not security reviewed), but it's totally open source so you can steal the bits you like: https://github.com/jrockway/jsso2 The end result is that I can open up Grafana on my phone and sign in with FaceID. Or if my face falls off, I can scan my YubiKey with NFC. All given to you for free for using WebAuthn. And it costs $0/month, which is much less than the Oktas of the world charge for a more
In Why Single Sign on Sucks
I have borg experience and I think Kubernetes is great. Before borg, I would basically never touch production -- I would let someone else handle all that because it was always a pain. When I left Google, I had to start releasing software (because every other developer is also in that "let someone else handle it" mindset), and Kubernetes removed a lot of the pain. Write a manifest. Change the version. Apply. Your new shit is running. If it crashes, traffic is still directed to the working replicas. Everyone on my team can release their code to any environment with a single click. Nobody has ever ssh'd to production. It just works. I do understand people's complaints, however. Setting up "the rest" of the system involves making a lot of decisions. Observability requires application support, and you have to set up the infrastructu
Read the rest
re yourself. People generally aren't willing to do that, and so are upset when their favorite application doesn't work their favorite observability stack. (I remember being upset that my traces didn't propagate from Envoy to Grafana, because Envoy uses the Zipkin propagation protocol and Grafana uses Jaeger. However, Grafana is open source and I just added that feature. Took about 15 minutes and they released it a few days later, so... the option is available to people that demand perfection.) Auth is another issue that has been punted on. Maybe your cloud provider has something. Maybe you bought something. Maybe the app you want to run supports OIDC. To me, the dream of the container world is that applications don't have to focus on these things -- there is just persistent authentication intrinsic to the environment, and your app can collect signals and make a decision if absolutely necessary. But that's not the way it worked out -- BeyondCorp style authentication proxies lost to OIDC. So if you write an application, your team will be spending the first month wiring that in, and the second month documenting all the quirks with Okta, Auth0, Google, Github, Gitlab, Bitbucket, and whatever other OIDC upstreams exist. Big disaster. (I wrote https://github.com/jrockway/jsso2 and so this isn't a problem for me personally. I can run any service I want in my Kubernetes cluster, and authenticate to it with my FaceID on my phone, or a touch of my Yubikey on my desktop. Applications that want my identity can read the signed header with extra information and verify it against a public key. But, self-hosting auth is not a moneymaking business, so OIDC is here to stay, wasting thousands of hours of software engineering time a day.) Ingress is the worst of Kubernetes' APIs. My customers run into Ingress problems every day, because we use gRPC and keeping HTTP/2 streams intact from client to backend is not something it handles well. I have completely written it off -- it is underspecified to the point of causing harm, and I'm shocked when I hear about people using it in production. I just use Envoy and have an xDS layer to integrate with Kubernetes, and it does exactly what it should do, and no more. (I would like some DNS IaC though.) Many things associated with Kubernetes are imperfect, like Gitops. A lot of people have trouble with the stack that pushes software to production, and there should be some sort of standard here. (I use ShipIt, a Go program to edit manifests https://github.com/pachyderm/version-bump, and ArgoCD, and am very happy. But it was real engineering work to set that up, and releasing new versions of in-house code is a big problem that there should be a simple solution to.) Most of these things are not problems brought about by Kubernetes, of course. If you just have a Linux box, you still have to configure auth and observability. But also, your website goes down when the power supply in the computer dies. So I think Kubernetes is an improvement. The thing that will kill Kubernetes, though, is Helm. I'm out of time to write this comment but I promise a thorough analysis and rant in the future ;)
In Kubernetes is our generation's Multics
U2F is the predecessor to the current standard, WebAuthn. If a web app supports WebAuthn, then that integrates with native keystores (Windows Hello, Face ID, whatever Android has), as well as hardware keys. The site operator has some flexibility to prefer certain methods (platform vs. external) and devices (attestation). I wrote an authenticating proxy that uses Webauthn: https://github.com/jrockway/jsso2. I don't think you should use it, but you can fire it up locally and try enrolling the various devices. Actually, you can just use Duo's demo: https://webauthn.io/
In What I Wish I Knew About U2F and Other Hardware MFA Protocols
I actually did exclude those on purpose, because I think they're somewhat out of scope -- arguably the point of running something like Authelia/Keratin/Dex/Keycloak/etc is to not write a single line of auth code, even if it's just wiring up a module/component. That said, here are some more in the space that I personally have earmarked: - (all-in-one) jsso2[0] - (all-in-one, embeddable) a12n-server[1] - (embeddable) node-oidc-provider[2] - (embeddable) node-oauth2-server[3] - (all-in-one, embeddable) authboss[4] - (proxy) vouch-proxy for NGINX[5] - (proxy) Grant with support for over 200 provider (!!)[6] [0]: https://github.com/jrockway/jsso2 [1]: https://github.com/curveball/a12n-server [2]: https://github.com/panva/node-oidc-provider [3]: https://github.com/oauthjs/node-oauth2-server [4]: https://github.com/volatiletech/authboss [5]: htt
Read the rest
In Authelia is an open-source authentication/authorization server with 2FA/SSO
Many things! jsso2: Identity provider and authenticating proxy for your non-enterprise use cases. WebAuthn only, no passwords! I was tired of typing a password for things like Grafana and PGAdmin, and IP whitelisting my home Internet for things that didn't have built-in authentication. https://github.com/jrockway/jsso2 If I were starting from 0 today, I'd just use Dex and Envoy's built-in OAuth support. OAuth is overly complicated, requiring a bunch of configuration for each app, and a ton of code in each app... but it won. So use that. jlog: I read a lot of log files in my day-to-day work and really like the idea of structured logs, but found them hard to read. jlog translates timestamps to my local time zone, lets me query them with jq, highlights errors with color, etc.: https://github.com/jrockway/json-logs Can't live without i
Read the rest
t, I use it many times every day, and have even convinced other people to use it without writing any documentation. (There are binary releases and a --help though!) "kubectl jq": I wanted to play with writing kubectl plugins, so I made one that is just "kubectl get x -o json | jq". I use it pretty regularly, but the Kubernetes client machinery doesn't give you autocompletion for free, so it's pretty painful to use. When they fix that, I plan to write more kubernetes extensions (including one that invokes jlog on the logs, saving a pipe ;) https://github.com/jrockway/kubectl-jq alertmanager-status: How do you know if your Prometheus/Alertmanager is working? If it breaks, it won't be sending you an alert, after all. https://github.com/jrockway/alertmanager-status ekglue: The good parts of Istio, for internet<->internal proxying, written by someone who read the xDS spec :P https://github.com/jrockway/ekglue For my day job, I work on Pachyderm Hub, which you should totally use if you want to run production-quality data science workloads (data provenance, reproducibility, etc.): https://hub.pachyderm.com/ I could write a lot about it, but basically... we have customers that want to use Pachyderm, but the complexity of Kubernetes stands in their way. How do you store logs? How do you monitor things? How do you give your coworkers access? We solve those problems by letting you click a button in a web UI. (As for why you'd want to use Pachyderm: https://www.pachyderm.com/use-cases/)
In Ask HN: What are you working on?
I am annoyed at doing auth over and over, when it's other people's software. The promise of the container revolution was that cross-cutting concerns would be handled by the infrastructure / orchestrator, and applications wouldn't have to care about details like authentication, monitoring, logging, etc. None of that really materialized, though. The actual running/scheduling of workloads is currently in a great state, but the cross-cutting concerns are pretty awful. Or actually, they're good, but very much "bring your own". I use managed Kubernetes, but it doesn't give me managed monitoring, managed logging, managed authentication, etc. (Cloud providers sell that, but you have to do all the integration work. Some random Go binary you download won't accept Identity Aware Proxy JWTs and send your metrics to Stackdriver. You have to ma
Read the rest
ke that all work yourself.) I've run into the situation at least twice where some app has bought into that mindset and made auth an external factor (don't send HTTP requests unless the user is authorized), and found that there was pretty much nothing good to provide that feature. So... I wrote my own thing both times, and am loving it. (You could use it too! But I wouldn't necessarily recommend it: https://github.com/jrockway/jsso2) I never have to think about auth again. Having also done the infrastructure and library work to get Prometheus/Grafana/Jaeger/Loki doing what I want (https://github.com/jrockway/opinionated-server), I am almost happy with the remaining cross-cutting concerns. I am ever closer to my "1 hour app", where I can just type in some code and have a fully-working production-quality app available to users. I'm not there, but I'm getting closer by the year. (Sometimes I wonder if we were wrong to totally get rid of the "just rsync some PHP files to a server" model. There were good things and bad things going on there; we should bring the good things back.)
In Sick of spending time on Auth, we built an open source 'Stripe for Auth'
I have my own take on this: https://github.com/jrockway/opinionated-server Some things we do differently, and some things we do the same. We give each RPC handler a logger, so you know where logs are coming from (and the trace ID associated with every message). We collect detailed prometheus metrics for every RPC, and send everything we know to Jaeger. We provide clients for outgoing RPCs that log and trace in the same way as incoming requests. We pick concrete types for logging/tracing/metrics, which makes it easier to figure out what code is actually running. Having used the abstraction layers, I find that when they don't do what you want, it can take a long time to figure out why. If you have to switch from Prometheus to Statsd or something, the performance and configuration characteristics of your app change, so you'll probably w
Read the rest
ant to manually revisit every metric. It's a straightforward refactoring that you will probably never do more than once, so I don't think it's worth making it "easy" out of the box. Finally, we let you configure your app with either flags or environment variables. Generally, I like flags for running things while developing (go run main.go --foo=bar) and environment variables for production. Why pick one or the other when you can do both! Extensive care has been taken to be able to log everything, including all payloads for bidirectional streams. (HTTP logging is a bit of a disaster; check out the code you have to write to be able to hook every type of http.ResponseWriter without the consumer noticing: https://github.com/prometheus/client_golang/blob/master/prom....) Some features that are missing or sub-optimal: * A long chain of interceptors for every request is very expensive. They should all be condensed into one wrapper that does "everything" explicitly. I don't think it's worth the debugging complexity to be able to compose a bunch of middleware at runtime; just write a function that wraps every request that does the stuff you want. If you want more stuff, type it in right there. Easy to read, easy for the computer to execute. * There should be fine-grained control over logging at runtime. I think you really want to be able to pass in configuration for every sub-logger, rather than a global log level. For example, you may want to adjust log sampling rate at runtime for a particular component, or upgrade a particular component from INFO to DEBUG for temporary investigation. (Without these controls, people stop writing log statements because they're too spammy, and then you have absolutely nothing to help you with ongoing issues.) * There is absolutely no support for mTLS, which is a crime in this day and age. This is probably the next thing that I'll add; you should be able to watch a volume for changes in TLS key/cert/ca material (so you can rotate keys frequently and without restarting), and require that incoming requests have a certificate trusted by the loaded CA. Outgoing requests should also be marked as "external" or "internal", and use the correct client cert for internal requests. (I somewhat promise to add this soon, because it's sorely needed.) * I don't think applications should support any non-production features for development, like a different logging configuration. opinionated-server apps take a --pretty_logs argument that configures it to print plain text instead of JSON, but I don't use it anymore; I just pipe the logs through jlog (`go install github.com/jrockway/json-logs/cmd/jlog`) and the results are much prettier than what zap would do itself. And it's the same tool I use every day to look at production logs, so there are no surprises. Ultimately, I wrote this because I like small pieces of software that do one thing, and found myself writing the same boilerplate over and over. Overall, this has been a success. I have written small utilities (github.com/jrockway/alertmanager-status, github.com/jrockway/nodedns, github.com/jrockway/alertmanager-discord, which I forked from someone else and converted to use opinionated-server), and larger applications (github.com/jrockway/jsso2, github.com/jrockway/ekglue), and overall not having to write the same monitoring/logging code over and over has proven quite productive. I have not achieved my goal of "1 hour to make a production application" quite yet, but opinionated-server is certainly helping.
In Golang web service framework with DI, Telemetry and more
I wrote this authorization code last night: https://github.com/jrockway/jsso2/blob/master/pkg/internalau... Obviously it's quite natural to just add interceptors as you need them and no doubt there are hundreds of things like this across the Internet. To some extent, I can't get over how much of a mess you can make by doing things like this. Because generated service definitions have a fixed schema (func (s Service) Method(context.Context, Request) (Reply, error)), you have to resort to hacks like propagating the current user through the context, instead of the easy-to-read and easy-to-test alternative of just passing in the parameters explicitly, as in func (s Service) Method(context.Context, types.Session, Request) (Reply, error). If I was going to spend time on infrastructure, that's the thing I'd fix first. Some other frameworks do
Read the rest
a little better here. We use GraphQL at work, and the methods are typically of the pattern: func AutogeneratedMethod(context.Context, ...) { foo := MustGetFoo(ctx) bar := MustGetBar(ctx) return ActualThingThatDoesTheWork(ctx, foo, bar, ...) } This makes testing the Actual Thing That Does The Work easier, and the reader of that method knows exactly what sort of state the result depends on (the most important goal in my opinion).
In Application Load Balancers enables gRPC workloads with end to end HTTP/2 support

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.