How can we make your first month awesome?

My first month at every job is a period of self-loathing, usually characterized by frequent white-hot panics in which I believe that I’m not good enough for the job, not a real programmer, or just profoundly stupid. This experience is what I thought everyone meant by the term “onboarding.”

So, when I looked at the schedule for PyCon this year, the talk “Technical on-boarding, training, and mentoring” stood out. I ducked in and sat in the last row, so I could easily slip away if necessary.

Instead of what could have been a soul-crushing grind about resource efficiency, I was delighted to hear the presenters Kate Heddleston and Nicole Zuckerman describe onboarding techniques that they had used to make new employees feel like humans welcomed into a group of other humans. Imagine if the next person we hired at Safari didn’t feel like we had set them on fire and asked them to find the water!

Activities for new engineers

As the talk progressed, I began to realize that we are all doing onboarding wrong. I wrote typo-ridden notes, struggling to keep up with all the great examples of onboarding activities that the presenters discussed, many of which I had never done nor asked a new person to do. Here are a few examples, paraphrased and sometimes given a Safari twist:

  • Buddy up the new engineer with the last person who got the development environment running

Not the most experienced person on the team, not the team lead or the person who built the dev environment from scratch two years ago, but the last person who set it up.

  • Ask the new engineer to start emailing things they didn’t understand or learned every week (2–3 things per week)

This one is great because even if a manager or a more experienced engineer sets aside time for one-on-ones, a new person might avoid or delay asking questions for several reasons. They might not want to bother someone who is obviously busy, or want to avoid asking what they think are foolish questions. Asking them to send questions invites them to open up and sets the expectation that they won’t understand some things. This could be a big win for some of the more reticent personalities joining a team.

  • Give the new engineer a map of people on the team, what they work on, and their areas of expertise

I wish that every time I had joined a team someone had given me this document. Imagine if, as a new engineer, you could easily find the person on the team who knew the most about Redis, or a particular internal web service or build process. Invaluable!

  • If they are more of a junior engineer, ask them to give a 5 to 10 minute presentation on a small topic biweekly or monthly (internal products, Python or JavaScript language features, testing methods). These should be things they can research independently that are useful to know.

This one is cool because it sounds super annoying, but it could really benefit junior programmers and interns. Just the other day, my boss was like, “How does SAML work again?” and I struggled through a hand-wavy explanation before giving up and admitting that I still didn’t have some of the details down. I guarantee you that if a junior engineer joins the team, I will ask them to give a presentation on SAML.

There was tons of other great advice, like having “code labs,” which are times that a new engineer could ask a more senior person any question, even something simple or embarrassing [A reddit AMA?—Ed.]. Also shadowing or short-term pairing, where the engineer sits (or remote screen-shares) with someone on the team to get exposure to the whole development workflow that the team uses.

Summing up, and more resources

One of the main ideas that I took away from the talk was that a new engineer’s first month could be very explicitly about the team welcoming them and guiding them through what is always a very complex, fast-moving world of new code and people. It sounded great, and I immediately wanted to go back and make the onboarding process at Safari even more awesome. I put together a proposed schedule of onboarding activities that we can try with new hires based on what the presenters suggested. I’m stoked for our next employee!

Kate Heddleston & Nicole Zuckerman gave a talk "Technical on-boarding, training, and mentoring" at PyCon 2014

The video from Kate Heddleston & Nicole Zuckerman’s great talk “Technical on-boarding, training, and mentoring” at PyCon 2014

Now that PyCon is over, the talks are all online, so you can watch a video recording of “Technical on-boarding, training, and mentoring”.

For a completely different perspective on onboarding, check out how WordPress does it by making everyone rotate through their customer service team (from The Year Without Pants).

Career transition: from a startup to a larger company

Over the course of my career I’ve spent most of my time working at smaller companies (less than 20 employees). I recently joined Safari, so the 150+ employees that work here is my first taste of a “larger company.” I realize to some that’s still a small company, but there’s no shortage of new experiences and things I’ve had to learn.

I’ve seen numerous posts on what it’s like to transition from a larger enterprise to a startup, but I haven’t read anything on the opposite experience. It’s been a wonderful experience so far, and the rest of this post summarizes my learnings.

Remembering names

To kick things off with a bit of humor, remembering names might be my biggest challenge so far. I’m terrible at this, so I find myself talking with coworkers and feeling bad that I have no clue who I just spoke with.

To my chagrin, everyone remembers my name. It helps to have Hipchat list names of coworkers, but remembering everyone is something that will take time.

Startup flexibility vs. BigCo entrenchment

If you work at a smaller company, they will tout the fact that they are more flexible than a large enterprise. This is generally true, yet doesn’t mean that larger companies can’t move quickly. I’ve been very surprised at how quickly Safari is moving.

In Clay Christensen’s book “The Innovator’s Dilemma,” one of the biggest challenges that companies face is when to invest in new technologies/markets. Typically disruptive innovation sneaks up on larger enterprises, and overtakes the old way of doing business very quickly (destroying the BigCo in the process).

This book serves as a cautionary tale, but my point is that many larger companies are fully aware of the need to constantly reinvent themselves. Safari is one of them.

As a result, large companies have smaller products/initiatives they are working on. This is essentially a startup inside a larger company, and there’s plenty of opportunities to move quickly, make an impact, and grow the business in a big way.

blah blah

Photo courtesy of Philippe Lewicki via CC BY-NC-SA 2.0

Balancing processes

I’m a big believer in the power of effective processes. There’s value in establishing a set way of doing things (larger companies) vs. unstructured tasks (typically work at a startup). Clearly this can be a double-edge sword. My role (marketing/growth) requires that I move at a fast pace, yet at the same time I must be cognizant of how to document issues in programs like JIRA and follow normal development sprints (still working on this). The key here is to balance normal processes, while still moving quickly.

Who should I talk to about ________ ?

At an early-stage startup, it’s normal to be the sole person responsible for a particular function. In a larger company, more teamwork is required. As a result, it can take time to understand the people who can help you accomplish particular tasks. If I had any advice on navigating through this process, it’s to ask questions. Get a copy of the company org chart or segment chat rooms related to particular projects.

The “make a difference” myth

Many people join startups because they want to make a difference. That’s a fantastic goal, but you can make a difference at a larger company, too. In fact, I daresay you could make a bigger impact at a larger company.

For example, Safari is participating in the ConnectED initiative, and providing $100 million dollars worth of technology resources to K-12 students.

How many startups have the resources to provide this? Not many.

I’m really excited about this, as I was in high school and would have loved to have access to the Safari library of books/videos. I’m thrilled to help the vocational center that I used to go to receive access to these resources, and they will be early “beta testers.”

Employment “risk”

Startups are not all fun and games. You might have your job one day and lose it the next. If you’re comfortable with ambiguity, a startup might be right for you. If not, I highly recommend working at a well-established organization. I tend to be risk averse, so there’s definitely a sense of comfort around knowing that the company you work for is profitable and growing.

Dynamics of a larger organization

If you work in a startup, and plan to sell your product/service to the enterprise, it’s probably a good idea to understand the dynamics of how a larger organization works. Who holds the credit card and needs convincing? Who’s in charge of a specific function, and what’s their decision-making process look like?

It’s for that reason that I recommend working at larger organization. There’s no better way to learn than by full immersion.

Wrapping things up

If you learned anything from this post, I hope it’s that you shouldn’t trust stereotypes of what it’s like to work at a startup or large organization.  Be open-minded and do your research.

I hope you enjoyed this post, and if you have any comments or thoughts, let me know on Twitter, or just comment below.

Coding while hiring

If you’re hiring people to write programs, you should work on a program with them.

This advice is nothing new but is too easy to ignore or botch. Switching my interviews to live coding on a real program is the single biggest hiring improvement I’ve ever made. It was helpful enough that I don’t think any of these concerns should stop you from doing the same:

  • Should there be a written test?
  • If so, how tricky should we make it?
  • How many days do they need to complete it?
  • Should they do it on a whiteboard to prove how good they are with markers?

As an engineering team, we’ve worked very hard to develop a culture that rewards programmers who learn to understand the business and our customers, and who make good choices about the right code (and quality) for the problem.

A lot of advice about coding tests comes from companies very different from ours. Instead of working on problems at the bleeding edge of distributed systems or category theory, we work on websites that delight and inform other programmers (and regular folk) with books and videos. That means that most of what I have read from others about interviewing sounds completely contrary to what we do. Instead of favoring a candidate that can plow through a ton of homework, I want someone with enough experience to ask the right questions and challenge shaky assumptions. Instead of picking someone who can write algorithms on the board, I want someone who can use their tools effectively and has great habits.

All this distaste for traditional interviewing methods meant that I was ripe for a change when I sat in on a CTO roundtable at an unconference a few years ago. The theme that emerged was hiring and I was fortunate enough to hear a few very good folks talk openly and honestly about the techniques they used. One shared some very clear lessons about how to do coding interviews and out of that I’ve built my own approach. Here’s the mechanics behind it.

Continue reading

Node.js is wonderful for robots

I was having a problem.

We use JIRA for ticket-tracking. It assigns each ticket a project code and ticket number, or key. I had been encouraging the team to refer to specific tickets in our chat room when discussing what they were working on, versus, “Hoping to finish up the thing with the error on the page.” My problem was that they started actually doing this, but there were now so many people collaborating that we had no idea what any individual “issue key” meant.

Them: Hey, Keith. I was noticing that there
  are a few dependencies linked to ZOMG-1337. 
  How's it going on BLOOP-9234?

Me: Uh...

We needed someone to help us with the menial task of looking up the associated JIRA ticket and summarizing the current status in all of our chatrooms. This sounded like a job for a robot. What surprised me was that it was also a perfect job for something other than Python, specifically Node.js.

An automated notification from GitHub triggers a response from jirabot

Continue reading

Believing in Robots: A Talk from Books in Browsers 2013

This is the outline of a talk delivered at the 2013 Books in Browsers Conference; link to video


  • Peter: I am opening for the PS Waverley, which is passing downstream.
  • Keith: Learn to forgive yourself
  • Peter: I am closing after the PS Waverley has passed downstream.
  • Keith: Everything happens so much
  • Keith: Your perfectly manicured hands are folded serenely in your lap. You re totally prepared. . .or are you?

Hi, I’m Keith and this is Peter. We’re weird.


We like robots, and we inhabit a world in which robots are real, and we communicate with them freely and on a daily basis. This morning we are going to talk about how some of these robots entertain us; some help us; and how we have accidentally employed a team of robots at Safari Books Online.

Continue reading

Building Distributed Teams: Driving meetings with Google Docs

Over the last few years, Liza and I have had the pleasure of building an ever-expanding engineering team. We’ve managed to find great people from across the country and were 100% distributed & office-less until a few folks moved into the new Safari office in Boston two months ago. Because our team was remote by rule rather than by exception, we’ve been forced to develop a culture that exploits new tools whenever they can help us cooperate and collaborate. One particular habit we’re fond of is running meetings through Google Docs.

As is typical with developers, we are not generally fond of meetings, especially recurring meetings, so we have tried to distill them into their productive, fundamental essence1. While our meetings are still far from perfect, I think we’ve developed some conventions worth sharing with other distributed teams.

One minutes to rule them all—in real time

Google Docs sometimes makes it too easy to create and share new documents, so the first lesson is to fight against this: use the same Google Doc for the same meeting week after week and write it during the meeting. This practice is laughably simple, but it removes the biggest threats to useful minutes:

  1. the attendees (claim) to not know where the minutes were/are
  2. the minutes feel worthless because they’ll be ignored forever after
  3. the attendees (wrongly) feel that someone else will write the minutes
  4. the attendees claim the minutes did not accurately capture the discussion

To set this up, just use an extremely clear title for the document (“{Team} {Purpose} Rolling Minutes”) and then add the new minutes at the very top for each meeting. Make it clear from the very first meeting that everyone is expected to help write the minutes in real time (plant some willing collaborators beforehand, if necessary).

It’s worth rotating to a new document every 6–12 months or Google Docs will be crashy.

Collect agenda beforehand (the “Pending” bucket)

Once you’ve established that the same document will be used for each meeting in the series, it is time to start turning the rest-of-the-week time into a lever that makes the meeting itself shorter. We keep an (empty) bulleted list under a Pending heading at the top of every minutes document. The Pending list gets filled by folks as something occurs to them throughout the week. In more extreme cases, the Pending list must be filled beforehand or the meeting itself is summarily canceled (depends on the meeting). Developing the Pending list asynchronously can also make it easier for less outspoken people to make sure their topics get some space in the larger forum.

Establish a repeating structure

While it’s easy to screw up, a carefully crafted meeting structure can help everyone understand when they’ll be actively participating and when the thing is nearly done. The problem is that you have to frequently evaluate the structure to make sure it still actually helps the team communicate rather than being wasteful boilerplate.

Our “big” meeting looks like:

(social pressure to finish what you promised)

(*extremely* short Before/Now/Next updates from each person
 don't skip this, as it gets every single human to actually say words at each meaning, 
 forces people to write down what they did [more social pressure],
 and establishes a basic record of what the team was doing in any given month)

(a heading for every item that was on the Pending list, plus anything emergent)

(every time a meeting ends without meaningful tasks assigned to specific humans, a kitten loses its wings)

A repeating structure also helps answer questions about who promised what. You just go down far enough to find it in the expected place in the minutes of a previous meeting. While this is a simple act, doing it consistently makes it clear that the minutes serve a purpose and that the each member of the team is accountable.

Force collaboration and attention through humor

The biggest benefit of cloud-based minutes is the opportunity to use a meeting as a way to help the group gel a tiny bit more, week after week. For distributed teams, the chances for true collaboration and team-building are already extremely limited, so we take whatever we get. Specifically, I want to use the minutes as a tool to have the team:

  • see each other actually (visibly) contributing to a shared project
  • laugh with each other
  • pay attention

A screenshot of a Google Docs document with humorous images and silly fonts

To achieve these goals, we need only two things: silly cat pictures, collaborative authoring. When the team knows that their colleagues are humorously defacing/lolcatting their section of the minutes, ignoring the document is nearly impossible (we don’t actually use Comments in minutes as much as you would expect). Juxtaposing the boss’ description of a particularly rough moment in the release process with a sad panda provides a rare moment to let off steam for people who almost never see each other face to face. And watching a document being written and edited by 5–10 people at once is really quite enchanting.

1 Andrew, our CEO, bought a huge stack of these and forced us to read them, before, ahem the next meeting.

Eight Great Tools Simple Enough for a CEO

Much of the early part of my career in publishing was spent writing and maintaining scripts used for automating book production. Applying the tools that developers use to manage code to managing manuscripts was a big part of the strategy behind the XML publishing toolchain I helped build (alongside @abdelazer) at O’Reilly (work now being impressively extended by Adam Witwer and Sanders Kleinfeld).

These days I spend much more time in spreadsheets and video conferences than in Vim, but I’ve never lost the appreciation for quality tools. I rarely write my own anymore, but here’s a list of tools I use every day that are indispensable for effectively working with a growing company that has team members around the world:

Google Apps for business

Get your discussions out of email (or worse, email attachments)! @liza and her team introduced us to using Google Docs for tracking running meeting notes, and from there our use of shared documents for everything from meeting agendas to press release reviews to training videos to board reports has grown dramatically. Some days the volume of documents getting updated feels overwhelming — until I remember that the volume of conversation hasn’t actually grown, it’s just been pulled out from where it was hiding in email. The full Google Apps suite is cost effective, easy to administer, and makes it simple to integrate authentication with third-party and internal apps.

Google Hangouts are a simple and easy alternative for video conferencing and screensharing — and Google Voice is a lifesaver for anyone who gets a lot of unsolicited sales calls.

Bonus tip: Comment notifications. It’s not well-documented, but you can use the Google plus “+” convention (or the Twitter “@“ convention) to add notifications to Google Docs comments. For example, if someone includes “” in a Google Doc comment, I’ll get notified by email.

Gmail keyboard shortcuts

I’ve used Outlook, Thunderbird, and over the years, but I’ve never been faster than when using Gmail right from Chrome — because of the extensive keyboard shortcuts. In general they mimic the Vim convention of modal editing, so they don’t require a lot of complex key combinations. To see the keyboard shortcuts from Gmail, just press “?” (that’s “Shift-/”) while your cursor isn’t in a text field and you’ll get a popover.


The concept is similar to Google’s Priority inbox, but the results are much better. SaneBox connects to your social media accounts to help it filter your email. It works great with Gmail, and is compatible with most IMAP-based email systems. My favorite feature is a folder called “BlackHole” — drop an email in there, and you’ll never see another one from that sender again.


The one feature I missed most from Outlook and Thunderbird when using Gmail via Chrome was the ability to schedule a message for later, so I was thrilled to find Boomerang. Boomerang’s main feature is to send an email from your inbox back to you later, but I use it almost exclusively for scheduling messages to send in the future. Unlike with Outlook, you don’t need to have your computer on for the message to go out. I often catch up on email in batches during odd hours, and it’s nice to be able to queue up replies for Monday morning while working on the weekend, for example.


While I’m not quite ready to compare them to polio, passwords are a constant aggravation. Having strong, unique passwords for everything and not having to remember any of them is wonderful. 1Password stores credit card info and other info (securely), and syncs with Dropbox to your phone. The Mac version is $49.99 and worth every penny (as is the $14.99 extra you’ll pay for the iOS version).


Expanding short abbreviations into longer text snippets sounds like a small thing, but it makes a big difference over time. Email salutations, phone numbers, addresses — it’s the closest thing I’ve found to Vim’s imap feature for use with everything else.


I tried Quicksilver a number of times, but couldn’t get myself over the learning curve. Alfred is similar, and I use it dozens of times a day for launching apps, looking up contacts (the PowerPack is worth the investment), and even doing quick calculations.


A theme with the tools on this list is that most of them only do one thing (or a small number of things) but do them very well. This last one is perhaps the best example of that. CloudApp puts a small icon in your menu bar. You drop files (or folders) onto that icon, and CloudApp creates a shareable link and puts it on your clipboard. I’ve been thwarted enough times by overzealous corporate IT departments with excessive restrictions on file attachment types and size that this is a very worthwhile preventive measure — since you can just send a link instead of an attachment.

There’s a lot more great apps on my laptop and my phone, but these are the essentials I depend on day-in and day-out to help keep the small stuff from getting in the way of the important stuff. Leave your own suggestions for indispensable tools in the comments below.

A Tale of Two Cities

Hurtling down I-25 at 70 miles per hour, a phone latches securely into its windshield mount, tapping the van’s electrical system to augment its small reserve. Many devices look up as it passes by, sensing a potential WiFi partner, but its transient signal is gone before a pairing can be made. A device on the same trajectory reaches out and shakes hands. A connection is made.

My son looks up from his notebook, “Ok mom. I’m connected.”

“Log in for your class or you’ll be late.”

“Yes mom.”

In London the teacher sits chatting with some early arrivals as she prepares to begin class. “Hi Micah,” she says as he enters the room. In two cities nearly half a world apart a student and teacher connect.

In Colorado Springs, Micah turns to this week’s chapter of “A Tale of Two Cities.” He’s not very fond of Dickens, but then how many 13 year-old boys are?

When I left a stable job of 12 years in south-east Michigan, I had no idea how transient our family would become. The economy took a nose-dive and the job market destabilized. Four years, six jobs, and five states later my wife and I are very glad we chose to homeschool after our first move. But what we have found is that we need help.

In many ways technology has served to separate people from each other. In the distant past people rarely left the town they grew up in. Most people I meet in Colorado were not born here, but have left their roots in search of work or pleasure. Technology has destroyed distance and increased distance at the same time.

But a brave new world lies before us. While several hundred years and a revolution separate us and our distant cousins in England, my son now chats with a teacher there in a way that would have been impossible 10 years ago. The world of online learning is a very different place than it was even four years ago when my family started this journey.

I’m just one engineer working on one small piece of learning technology. But I’d like to think I’m contributing to a revolution.

When Micah gets home I ask him what his teacher gave him for homework.

“I have to write a descriptive essay about a mango or a piece of fruit.”

Sis replies, “Maybe you should write a descriptive essay about dad’s nose.”

That would be a long tale indeed.

Google Apps Auth for Internal Django Sites

Usernames and passwords are lame. Everything that makes them lame on the wider web makes them doubly lame on your company intranet. Here’s how we stopped writing password reset forms.

At Safari, we’ve been trying to make it easier to prototype little applications to show to our colleagues. At the start of the year, we also switched the entire company to Google Apps for Business. While this has mostly been a win for our IT staff and coworkers (with some major exceptions), the range of APIs and developer-focused services provided by Google is tremendous. In particular, it is incredibly straightforward to wire together Django, the django-social-auth package, and Google’s OAuth 2.0 identity service to create secure web applications that are only available to our colleagues. And no more password forms.

API Credentials

The first step in using Google to manage your identities for your Django project is getting API credentials from Google:

  1. Sign into your Google Apps account in your browser
  2. Visit in the same browser
  3. On the left menu, Create a new Project
  4. To start, you don’t need any Services, so select the API Access tab rom the left menu and “Create an OAuth 2.0 client ID…”
  5. Fill out the Client ID form for a “web application” and use localhost:8000 as your hostname

Now that you have API Access, you need to Edit settings for the new “Client ID for web applications” you just created. Specifically, you need to enter new “Authorized Redirect URIs” (one per line):

http://{dev server}/complete/google-oauth2/
https://{prod server}/complete/google-oauth2/

These are the URLs that Google will return the user to after they have authenticated. Omit the dev server and prod server if you don’t yet know them.

Next, we’ll use those credentials to setup the django-social-auth package, so keep this page open.

Using django-social-auth

django-social-auth is a great package for getting started quickly, in part because it supports a wide range of services out of the box and also because it has detailed documentation.

After you’ve installed the django-social-auth package inside your virtualenv, you need to follow the basic configuration instructions for your Django project. In your, make sure 'social_auth' is in the INSTALLED_APPS and then run ./ syncdb to get the new tables that django-social-auth requires.

You will also need to add a few more things to

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Django Social Auth Config

    '',  # putting this 1st means that most users will auth with their Google identity
    'django.contrib.auth.backends.ModelBackend',        # ...but this one means we can still have local admin accounts as a fallback

LOGIN_URL          = '/login/google-oauth2/'       
LOGIN_ERROR_URL    = '/login-error/'

SOCIAL_AUTH_PROCESS_EXCEPTIONS = 'social_auth.utils.log_exceptions_to_messages'  # ...assuming you like the messages framework

GOOGLE_OAUTH2_CLIENT_ID      = 'yourCLIENTidHERE'  # this is on the credentials web page from above
GOOGLE_OAUTH2_CLIENT_SECRET  = 'YOURsecretHERE'    # this is also on the credentials web page from above
GOOGLE_WHITE_LISTED_DOMAINS = ['']  # this is what actually limits access

SOCIAL_AUTH_COMPLETE_URL_NAME  = 'socialauth_complete'
SOCIAL_AUTH_ASSOCIATE_URL_NAME = 'socialauth_associate_complete'

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The most important line from the above is the GOOGLE_WHITE_LISTED_DOMAINS. It’s this setting that limits access to users inside your organization.

Views and URLs

Now that we’ve got auth from Google, we need to wire it up. For a normal application, you’ll want to create a typical view and template for logging in, errors while logging in, a logout view (to delete your cookies), and then ensure you are using the login_required decorator or other access control. For this blog post, I’ll just sketch these out, based mainly off your main

from django.contrib.auth.decorators import login_required
from django.contrib.auth.views import logout
from django.views.generic import TemplateView

urlpatterns += patterns('', 
    url(r'', include('social_auth.urls')),                                          # we absolutely need these ones

    url(r'^$', TemplateView.as_view(template_name="login.html")),                   # also fairly important
    url(r'^logout/$', logout, {'next_page': '/'}, name='gauth_logout'),             # this one is nice, but not totally required

    url(r'^login-error/$', TemplateView.as_view(template_name="login-error.html")), # if you've set up messages, you could loop through them here

    # Now we can test whether this stuff works
    url(r'^secrets$', login_required(TemplateView.as_view(template_name="secrets.html"))),  


If we set this up and then create a secrets.html in our templates directory:


… and a login.html in our templates directory:

<p>Use your work email credentials to sign in to this application: 
  <a href="{% url socialauth_begin 'google-oauth2' %}?next=/secrets">Sign In</a>

At this point, you should be able to start the Django debug server with ./ runserver.

Trying it out

If you visit http://localhost:8000/secrets with your browser now, you should be able to try it out. First off, you should not see your secrets yet (even if you are logged in). Before you get there, you need to both be logged into a Google account and grant access to let Google give your identity to this new application. After that happens, Google and django-social-auth will double-check that you are legit and pass the GOOGLE_WHITE_LISTED_DOMAINS. Finally, Google will send you back to the application and in this case you will be redirected to your ?next param.

Do also try it with a personal GMail account to make sure it errors with the login-error.html template. That’s the GOOGLE_WHITE_LISTED_DOMAINS at work.


Well, the most obvious failure is that you use a browser that is logged into your personal GMail rather than your Google Apps for work. The less obvious failure is that this will only work locally if you are running the Django debug server on port 8000 and putting localhost:8000 into your browser ( won’t work).

It’s probably also worth adding this to one of your loggers inside your LOGGING:

        'SocialAuth': {
            'propagate': True,