Same Company New Team

Pre-Auth0

In 2016 I made the move to join a startup in the identity space. I was a little nervous to leave my company at that time. I was in a very comfortable environment where I had the respect from my peers and leadership. At the time the nagging reason to find opportunities outside organization was driven by too few challenges as an engineer and not enough opportunities to grow. The problem was comfort. It was simply too comfortable and I didn’t have anything pushing me forward. I am a highly driven person, but having external motivators is an important aspect of a position for me.

One morning a really close friend pinged me asking to chat about Auth0, where he recently was hired. Out of curiosity I said let’s do it. Also, I was eager to meet, because I knew about Auth0 and was using the product in some of my side projects I was eager to hear how my friend was doing in his new role. The morning we met he made his motivations crystal clear. He wanted to share how great the organization was and express how I might do well woring at Auth0. It didn’t take much convincing, Auth0 was something I really enjoyed working with for my side projects. When working at Hallmark Business Connections (a subsidiary of Hallmark Cards) I built and maintained all of the federated integrations and built the OAuth 2 based authorization server so it felt congruent with my passion twoards identity.

That night I remember talking to my wife about me possibly leaving Hallmark. Hallmark treated me well and I owe a lot to that organization. It also didn’t help that my wife and I had a 2 year old son with another kiddo on the way. Leaving a comfortable position with a lot of job security was a bit scary. However, I knew this was my opportunity to be apart of something amazing. My wife’s reaction was a bit shocking. She told me flat out, “You’d be silly not to give it a shot.” And so it was set, I made up my mind. Easy as that.

Auth0 - Day 1 Happy and Terrified

I remember my first day. I hit a coffee shop and then instead of doing my daily commute I headed back home to sign in to my new laptop. This was an amazing perk for my new job (WFH and no traffic). I was in love with the experience from day one. A brand new position, and I was 100% set ready to roll on day one. This is all too rare. I was greeted with a ton of welcome messages by people all over the world that I’ve never met. I did recognized many of the names in the slack channel of people I followed on Twitter, Medium, and all sorts of channels. Then it hit me like a sledge hammer. I just realized that I was no longer the gray wolf of the organization, the go to person, the hero. To the team I was probably just some random person, the new guy with the weird dog named Jim (he is a corgi lab mix).

First 3 Months - Imposter Syndrome

We are all susceptible to imposter syndrome every now and again. Some of us deal with it daily. When I started working with some incredibly talented people I had to deal with imposter syndrome every day and still do today.

I remember coming into a company where I had zero reputation. I had to start all over again and this time in a space with some of the best engineers I’ve met. The first few months were really hard on me mentally due to the demands and goals I held myself accountable to achieve. I had to ramp up on a new product and new domain. I also had this internal pressure to add value and find my place in the organization, to make a name for myself. In the first few months I read everything I could find about the identity space and our product. I talked to as many people as I could to develop relationships and network. I tried super hard to focus on learning and let the carving out my niche amongst the talented individuals goal come together on its own. I just wanted to be effective in my role and get some early wins and provide value right away.

I may be giving you the impression this sounds crazy, but honestly this was an amazing experience. I had the support of an awesome team who was happy answering all of my questions and collaborating on things I didn’t yet know. I had the support of a great manager German Matosas. He provide all the resources and support I needed to succeed. In fact I’ve had a lot of great managers in my career. So despite the challenges and internal pressures I faced I would not change a thing. This environment allowed me to rapidly grow and push me. I quickly leveled up and started making a name for myself as someone who knew his bits, but also the team saw me as dependable and knowledgable. This was a huge win for me and I am very thankful to my team, because they let me know how much I was appreciated and gave me really solid feedback (constructive and praise). The open and transparent environment was amazing and super welcome.

Many Hats and Many Roles

When you join a start up you are signing up for a position that will require you to do many things. This is another thing that originally attracted me to this role. I knew I wasn’t going to get bored. In this position I was an engineer responsible for building and maintaining Auth0 extensions, helping customer design and build identity in to their products, and manage core infrastructure for our private cloud instances (virtual appliances). I had my hands in a lot of work streams and it was awesome, though sometimes stressful when a few competing priorities jumped out :). That said it was a hell of a ride and again a great learning opportunitty.

Scaling the Team

Auth0 has blown up (in an awesome way) since I’ve started. It feels we are riding a rocket to the moon. This means we needed to start scaling our teams for success. My team was part of the remix. Our position was split into 3 roles: extension engineering, appliance services, and professional services.

During this transition I was woried I’d lose a bit of what I loved, that is, to build a product used by developers. I was also in a position that I was ready to do another tour of duty. I spent some time evaluating the various engineering teams and found two roles I loved one on our authentication team and our appliance engineering team. I talked with both leads which made the decision nearly impossible. Both leads were people I highly respected and both could help me continue to grow. I ultimately decided on appliance engineering for two reasons. First, it felt like there was more opportunity to influence the direction of the appliance. The appliance has so much potential to do awesome things and I felt like I could really make an impact there. The second was a gut feel about where I thought I would do better. Honeslty, I think my imposter syndrome influenced this second point. I know now that I am certainly capable to provide value to that team and I could have saved myself a whole heap of time if I had flipped a coin.

To My Current Team

After the 2018 offsite I left Panama feeling super sad. During the offsite I got to reconnect with my team, meet my new boss (Jonno King), and was excited about our team’s vision and future. This team has always been a high performing team, but the future will only get brighter as we’ve broght in several crazy talented people.

I want to make a quick statment to my team. This group is extremely special. We are building something that will help Auth0 and our customers succeed. We are helping our customers build valuable solutions that not only protect our customers brands, but our solutions protect the identities and data of our customer’s users. The work we do in professional services is absolutely critical. This team is busting at the seams with f*cking smart and genuine people who care about the work we do. I cannot thank each of you enough for all the support, collaboration, drive, and friendships. Without this team I never would have grown my skills to the degree I di over the last year and a half. Thank you and I will always be in your corner. I hope we continue to push each other forward and I really hope we land on the same Auth0 team in the future.

In Reflection

Since the offsite I spent a lot of time reflecting on the decision I made. I talked with my current boss, my old boss, and my future boss about my past and future with Auth0. What I found is not surprising… everyone of these people really cares about helping me find the right path. Each one of them wanted me to feel good about where I land inside or outside of Auth0 (I never considered leaving, but I wanted to point this out). Each of these people care about making sure I made the right decision for me and then letting me know the support was there. They even went the extra mile to share, from their viewpoint, how I could help Auth0 succeed from within their teams.

My current boss made it more difficult to leave my current team because he had me believing in him and his vision and how I would help. Chatting with the auth lead had second guessing my choice to join appliance engineering instead of authentication. Not because of guilt, but because I really felt inspired about the vision and how I could fit in. Finally, when talking with my soon to be new boss I felt re-motivated and inspired by the opportunity ahead for the same reasons. I share this, not because I can’t keep my shit together, but bercause I realized that I was valued by the organization and each opportunity had a leader that saw how I could help that team. Also, each leader had a clear vision that was motiovating and inspiring. I went from terrified newbie wanting to make his path to someone who was desired by several teams.

At the offsite I won a peer award. I was given a trophy and then celebrated on stage with an applaus from all my peers. I was litterally having a HTF (how the f…) moment and wondering if it was a mistake. This is one of the most meaningful and memorable awards I’ve earned, because it was given to me by the people I came into Auth0 thinking were amazingly talented. People I tried hard to learn from. Now, they are awarding me for something meaningful. This litterally made me feel awesome as though I am doing the right things and carving my place out in Auth0.

So to my company and coworkers/friends my deepest thank you. I am better everyday because you all lead by example and drive me to learn and push myself outside my comfortzone. Anyone of you should have won that award and I was lucky to have my name called that day and it was because of you.

Auth0 - The Future

Looking forward I am happy to announce I will be transitioning to the appliance engineering team on June 1. I am super excited for this next chapter and to see how my new team and I can help Auth0 and our customers win. To my new team: I am going to work hard everyday to do my part and I know you will hold me accountable to that. Let’s build awesome things together.

Cheers!

Debugging and Troubleshooting Auth0

I have talked to a number of people about debugging and troubleshooting issues when using Auth0. When writing code it doesn’t take a long time to stumble across a need to get a deeper sense into what failures are ocurring. In this quick post I want to share some of the tools that are available for tracking down issues in production or when developing new features.

Production Issues

Auth0 makes it simple to build authentication and authorization into your product, but sometimes things can go wrong or users can stumble into unexpected workflows. When these bugs happen we want to be able to identify the problem and respond quickly. Fortunately, Auth0 provides a nice log function that expose the details we need. For nearly all user and dashboard admin actions in your tenant (successful/failed login, success/failed code exchange, forgot password, etc) Auth0 logs information regarding these interaction. Take a look at Auth0’s Data Event Listing document for a full list of all the events.

This is pretty straight forward. Using these logs you can monitor and search for failures and information regarding the behavior. In addition to this log Auth0 will share, per user, a historical view for each user. Simply navigate to Users, select a user, and the click on history. This will show roughly 30 days of history associated with that user.

In some environments it is not ideal to give dashboard access to everyone who needs access to the logs. To handle this Auth0 supports various extensions that will pipe log data to a number of providers like Splunk, Mixpanel, Logly, etc. Once you’ve setup integration you can monitor and search for various events. Lastly, if Auth0 does not support the log provider you use there is a Log API endpoint that is exposed so you can build your own integration.

Debugging

Auth0 has several extensibility points where developers can run code to customize authentication and authorization workflows. Whether we are build a custom database integration, creating a custom authorization policy via a rule, or using one of auth0 various hooks you can output console.log('super helpful output.'); and stream this data live to your terminal or the Real-tim Webtask Logs extension. These two tools will allow you see real-time log output in any of the Auth0 extensibility points (Hooks, Rules, Database Action Scripts). Setting up the extension is the easiet way to get started. Navigate to the Extension Gallery, search for Real-time, and click the extension to insall it. Once the extension is installed you can click on it again to open the extension in a new tab. Before you are able to view the log stream it will ask you to login with your Dashboard admin credentials. Once you are authorized you will see a live stream of all the activity across Hooks, Rules, and Database Action Scripts.

Sometimes it is not ideal to use a browser to stream these details. Instead you can stream this information straight to your terminal.

# Install the Webtask CLI
npm install -g wt-cli

# Setup your webtask profile
wt init --container "{your-tenant-name}" --url "https://sandbox.it.auth0.com" -p "{your-profile-name}" --auth0

# Stream Logs
wt logs -p "{your-profile-name}

If all is setup properly you will start seeing the data stream to your terminal!

Migrating Git Repositories with Full History

Earlier this year GitHub announced a pricing change and unlimited private repositories. I really like using GitHub and have decided to migrate my free Bitbucket repositories over to GitHub. At first I was hesitant, because I wanted to retain my entire commit history. Well, with Git this is a pretty trivial task.

We are using some basic features in Git and it may be useful to check out the documentation for mirror and remote. Git mirror didn’t have a fancy fragement URL so here are those docs for convenience.

–mirror

Set up a mirror of the source repository. This implies –bare. Compared to –bare, –mirror not only maps local branches of the source to local branches of the target, it maps all refs (including remote-tracking branches, notes etc.) and sets up a refspec configuration such that all these refs are overwritten by a git remote update in the target repository.

In order for this to work, we’ll want to create an exact copy of the BitBucket repository locally. We’ll do this by creating a bare, mirrored clone.

 git clone --mirror https://your_username@bitbucket.org/your_username/your-git-repository.git

Once we’ve created the local clone, we’ll want to change the origin of the repository. Chances are, since this repository lives at Bitbucket, the origin is something like https://your_username@bitbucket.org/your_username/your-git-repository.git. We’ll want to swap this for the GitHub repository URL.

git remote set-url --push origin https://github.com/your_username/your-git-repository.git

After the origin remote was upated to point to the new GitHub repository we’ll need to push the mirrored repository.

git push --mirror

These steps above are a good way to migrate your respositories with full history. It is also possible to add a second remote to your existing repository, if you wanted to keep the existing origin. Here is a gist.

Introduction to Content Negotiation

Content Negotiation, simply put, is a way for a client and/or server to determine how content is requested and received over HTTPS (or HTTP, please be kind use HTTPS). Fortunately, for developers, content negotiation has been defined by the W3C and you can find the specification on their site (RFC2616 Section 12). There are three types of content negotiation, but for the purpose of this article we’ll focus on server-driven negotiation. That is when the agent or client requests content using HTTP headers to help the server make decisions on how to format data sent back to the client. Here are the headers that are typically used in content negotiation: Accept, Accept-Charset, Accept-Encoding, Accept-Language, etc.

The fastest way to see content negotiation in action is to open up Chrome development tools, navigate to the network tab, and go to any website. If you click on the requst you will notice Chrome automatically populates the Accept, Accept-Encoding, and Accept-Language with the values below. These two headers are how Chrome negotiates with the server how it prefers to recieve content for the given request.

GET / HTTP/1.1
Host: www.google.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8

Let’s break this down a bit. The Accept header is used to specify the media type for data returned in the response body. The Accept header states a weighted preference for the desired media types. In this example Chrome requested HTML, then xhtml, followed by xml as it highest preference. After that, Chrome states it will accept an image/webp followed by anything. Chrome uses the Accept-Encoding header to specificy how it wants the response encoded. Finally, it requests the en-US language as its preferences otherwise a non-localized version of English second using hte Accept-Language header.

The server, if using server-driven negotiation, can opt to take any of these headers into account when making a decision on how to return the content. It is important to note the user agent or client does not control how content is returned. It simply declares preferences with each request. In server-driven content negotiation the server’s algorithm is reponsible for making a determination (or Best Guess as it worded in the specification). Most servers will look at these HTTP headers when deciding how to format content on the response.

As developers we often need to know more about content negotiation when building HTTP(S) based services. After consuming a few APIs and web services it becomes apparent that many web services have different implmentations and limitations with content negotiation.

Experimenting with content negotiation and the bits

Using Postman, I generated this request to an ASP.NET Web API running locally. The request uses the Accept HTTP header requesting the server respond with XML.

GET /api/Person HTTP/1.1
Host: localhost:65307
Accept: application/xml
Cache-Control: no-cache

By default, ASP.NET responded with the xml media type. The server made its decision based on the Accept header. ASP.NET has a more complex set of rules than this, which we will dig deeper into in a future article.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?XFxnY2MuaW50XHVzZXJzXGhvbWVcc2hhd25tXHZpc3VhbCBzdHVkaW8gMjAxNVxQcm9qZWN0c1xEZW1vXERlbW9cYXBpXFBlcnNvbg==?=
X-Powered-By: ASP.NET
Date: Sat, 09 Jul 2016 11:27:20 GMT
Content-Length: 194

<Person xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Demo.Models"><Age>30</Age><FirstName>Some</FirstName><LastName>Dewd</LastName></Person>

Today, many developers prefer to use JSON. To receive JSON data over XML, simply update the request’s Accept header with the media type application/json.

GET /api/Person HTTP/1.1
Host: localhost:65307
Accept: application/json;q=0.9,application/xml;q=0.8
Cache-Control: no-cache

As one can see the server responded with equivalent data. This time, instaed receiving XML the server responded with a JSON string in the response body.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
Date: Sat, 09 Jul 2016 11:34:22 GMT
Content-Length: 47

{"FirstName":"Some","LastName":"Dewd","Age":30}

To show off more interesting behavior in ASP.NET’s server-driven content negotiation we can provide a media type not supported out of the box. Optionally, if one were to leave off the Accept HTTP header one would get the same result. The ASP.NET content negotiation algorithm cannot provide a response requested by the client, it will fall back to its default media type formatter (for .NET this is application/json).

GET /api/Person HTTP/1.1
Host: localhost:65307
Accept: text/html
Cache-Control: no-cache
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
Date: Sat, 09 Jul 2016 13:16:56 GMT
Content-Length: 47

{"FirstName":"Some","LastName":"Dewd","Age":30}

ASP.NET is just one technology of many for building web services. GitHub also uses server-drive content negotiation, but implments a different behavior. For example, unlike ASP.NET WebAPI’s default behavior, GitHub does not fallback to a default media type formatter if one requests an unsupported media type. Instead, GitHub opts to respond with an error formatted in JSON.

GET /user/sgmeyer/repos HTTP/1.1
Host: api.github.com
Accept: application/xml
Cache-Control: no-cache
HTTP/1.1 415 Unsupported Media Type
Server: GitHub.com
Date: Sat, 09 Jul 2016 13:23:14 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 167
Status: 415 Unsupported Media Type
X-GitHub-Media-Type: unknown
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1468074180
Access-Control-Expose-Headers: ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
Access-Control-Allow-Origin: *
Content-Security-Policy: default-src 'none'
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-XSS-Protection: 1; mode=block
X-GitHub-Request-Id: 325142E0:2FFB:80ACDE9:5780FAC2

{
  "message": "Unsupported 'Accept' header: [\"application/xml\"]. Must accept 'application/json'.",
  "documentation_url": "https://developer.github.com/v3/media"
}

Content negotiation is a great way to improve the developer experience of an API. One can provide conveniences for customers by allowing them to determine the format of data coming back from the service. There are many ways to implement content negotiation, but when understood it can be a power tool as a developer.

TFS Source Control Explorer Performance Issue

The last few weeks I have noticed a steady decline in the performance of TFS Source Control Explorer. I first noticed performance degradation when I was traversing the tree view of the directories under source control. Each time I expanded a node in the explorer window it would spin for 5-10 seconds at each level. After a while I began to notice get latest, shelving, and committing was coming to a snail’s pace. Today I had enough and decided to dig into the issue, admittedly I waited too long before solving this problem.

To keep this short and sweet TFS does not like to handle a workspace with over 100,000 files. The problem I was having is that each branch I created went into the same workspace. This was clearly a boneheaded move and one that was easy to mitigate. Ultimately, I decided to create a separate workspace for each branch. Once I had made this change TFS Source Control Explorer, and TFS management was much faster.