Skip to content

Instantly share code, notes, and snippets.

@WebPlatformDocs
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WebPlatformDocs/46fd83e3d198b96a6e0f to your computer and use it in GitHub Desktop.
Save WebPlatformDocs/46fd83e3d198b96a6e0f to your computer and use it in GitHub Desktop.
Firefox Accounts deployment configuration at webplatform.org

See also the canonical version

Installing Firefox Accounts ("FxA")

Procedure to install Firefox Accounts system to WebPlatform infrastructure. To read more about the context and the project of adapting FxA for WebPlatform infrastructure, head over to WPD:Projects/SSO/Adapt Firefox Accounts for WebPlatform

OAuth terminology regarding grants/roles/entitlement

seanmonstar: ... the oauth spec uses "grant" where we use "code". OAuth server sends a code to app, and the app trades the "code" for a token.

TODO

  • Database schema, see https://github.com/mozilla/fxa-auth-db-server/tree/master/db/schema, and add:

      ALTER TABLE accounts 
          ADD COLUMN `username` VARCHAR(55) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NULL DEFAULT NULL ,
          ADD COLUMN `fullName` VARCHAR(255) NULL DEFAULT NULL AFTER `username`,
          ADD UNIQUE INDEX `username_UNIQUE` (`username` ASC)
      ;
    

Procedure

Install Firefox Content server

The component that humans sees in their web browsers.

Start by system dependencies

sudo apt-get install nginx-full git nodejs npm libgmp-dev libgmp10 pcregrep

Ubuntu package-names collision fix, we want nodejs, not radio amateur utility.

sudo ln -s /usr/bin/nodejs /usr/bin/node

Deployment specific requirements:

sudo npm install -g grunt-cli phantomjs bower bunyan

Creating folders:

sudo mkdir -p /srv/webplatform/auth/
sudo chown -R ubuntu:ubuntu /srv/webplatform

Download package and extract

curl -o fxa-content-server.tar.gz https://codeload.github.com/webplatform/fxa-content-server/tar.gz/webplatform-customizations
tar xfz fxa-content-server.tar.gz 
cd fxa-auth-content-webplatform-customizations

Install dependencies

npm install --production
bower install

Note that you can see available options the project base Convict file. Those files are easy to find, they are generally called config.js outside of the config/ folder. Mostly in lib/. The Confict files shows all options and shows the defaults.

more server/lib/configuration.js

Configuration notes:

  • fxaccount_url: Is where you will expose the fxa-auth-server, ideally through a HTTP server that has a valid SSL certificate, in our case api.accounts.webplatform.org

Configuration and startup, refer to fxa-content-server config block below.

Install Firefox Account Authentication service

Install the package

cd /srv/webplatform/auth
curl -o fxa-auth-server.tar.gz https://codeload.github.com/webplatform/fxa-auth-server/tar.gz/webplatform-customizations
tar xfz fxa-auth-server.tar.gz 
cd fxa-auth-server-webplatform-customizations

Install dependencies

npm install --production

Note that you can see available options the project base Convict file.

more config/config.js

The file name can match the environment name. For example, if you use NODE_ENV=prod, the file would be config/prod.json

Configuration notes:

  • contentServer: Is the URL where the fxa-content-server is
  • templateServer: Is, also, where the fxa-content-server (At the moment). This is where the email templates are accessible, and they will most likely change location in an unknown future.
  • customsUrl: Will eventually be the email checker called "Customs", can be set to "none" if not in use (current default)

Configuration and startup, refer to fxa-auth-server config block below.

Install OAuth service

Get the package

cd /srv/webplatform/auth
curl -o fxa-oauth-server.tar.gz https://codeload.github.com/webplatform/fxa-oauth-server/tar.gz/master
tar xfz fxa-oauth-server.tar.gz
cd fxa-oauth-server-master

Install dependencies

npm install --production

You can see the available configuration switches here:

more lib/config.js
more config/dev.json

Configuration notes:

clients: Is an array of objects that is used to allow clients. At every startup, the OAuth server ensures that the client entries are inserted in the database and allows a remote site to use us as an OAuth server. To have preauthorized clients, look at the client property "whitelisted".

  • contentUrl: Should point to the OAuth endpoint context root, e.g. https://accounts.webplatform.org/oauth/
  • whitelisted: in a client entry. This property is useful to differentiate services that we want to pass through OAuth without asking each user to confirm the use. To learn more about generating keys, you can see it in the fxa-oauth-server/doc/clients.md

Configuration and startup, refer to fxa-oauth-server config block below.

See also

Install Profile service

Get the package

cd /srv/webplatform/auth
curl -o fxa-profile-server.tar.gz https://codeload.github.com/webplatform/fxa-profile-server/tar.gz/webplatform-customizations
tar xfz fxa-profile-server.tar.gz
cd fxa-profile-server-webplatform-customizations

Install dependencies

npm install --production

You can see the available configuration switches here:

more lib/config.js
more config/dev.json

Configuration, refer to fxa-profile-server config block below.

Configure NGINX

Note, we are creating self-signed for the moment.

sudo -s
cd /etc/nginx/ssl

From here, you have two choices:

  • Install your key and certificates
  • Create self-signed certificates

It is expected that you have the following files in /etc/nginx/ssl

Adjust vhost:

vi /etc/nginx/sites-enabled/accounts

Paste:

server {
    listen      80;
    server_name accounts.webplatform.org;
    return      301 https://accounts.webplatform.org$request_uri;
}

server {
    listen      80;
    server_name api.accounts.webplatform.org;
    return      301 https://api.accounts.webplatform.org$request_uri;
}

server {
    listen      80;
    server_name oauth.accounts.webplatform.org;
    return      301 https://oauth.accounts.webplatform.org$request_uri;
}

server {
    listen       443 ssl;
    server_name  accounts.webplatform.org;

    location / {
      proxy_pass http://127.0.0.1:3030;
    }

    ssl on;
    ssl_certificate     ssl/accounts.webplatform-20140401.pem;
    ssl_certificate_key ssl/201404.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

server {
    listen       443 ssl;
    server_name  api.accounts.webplatform.org;

    location / {
      proxy_pass http://127.0.0.1:9000;
    }

    ssl on;
    ssl_certificate     ssl/api.accounts.webplatform-20140401.pem;
    ssl_certificate_key ssl/201404.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

server {
    listen       443 ssl;
    server_name  oauth.accounts.webplatform.org;

    location / {
      proxy_pass http://127.0.0.1:9010;
    }

    ssl on;
    ssl_certificate     ssl/oauth.accounts.webplatform-20140401.pem;
    ssl_certificate_key ssl/201404.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
}

Remove default nginx vhost

rm /etc/nginx/sites-enabled/default

Return as normal user

exit

Create self-signed certificates

Paste our own self-signed CA authority (eventually will be real ones)

vi ca-cert.pem
vi ca-key.pem

Optionnal If you do not have your own certs to use as root of your own self-signed authority, you can make your own with this:

openssl genrsa 2048 > ca-key.pem

openssl req -new -x509 -nodes -days 3600 \
    -key ca-key.pem -out ca-cert.pem

Generate certificate request:

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out accounts-req.pem -subj '/C=US/ST=MA/L=Cambridge/O=W3C/OU=WebPlatform Project/CN=accounts.webplatform.org/emailAddress=hostmaster@webplatform.org'

openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out api.accounts-req.pem -subj '/C=US/ST=MA/L=Cambridge/O=W3C/OU=WebPlatform Project/CN=api.accounts.webplatform.org/emailAddress=hostmaster@webplatform.org'

Generate self-signed certificate:

openssl x509 -req -in accounts-req.pem -days 3600 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out accounts-cert.pem

openssl x509 -req -in api.accounts-req.pem -days 3600 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out api.accounts-cert.pem

As described in NGINX SSL Module documentation about SSL certificates;

When using a chain of certificates, just append the extra certificates to your .crt file. The server certificate needs to be the first on the file, otherwise you'll get a mismatch between private and public keys.

Rename them fo follow the conventions given in the rest of the procedure.

mv accounts-cert.pem accounts.webplatform-20140401.pem
cat ca-cert.pem >> accounts.webplatform-20140401.pem

mv api.accounts-cert.pem api.accounts.webplatform-20140401.pem
cat ca-cert.pem >> api.accounts.webplatform-20140401.pem

mv server-key.pem 201404.key

fxa-content-server

To run the server in development mode, use the grunt server command. Without argument, it'll be using the server/config/local.json file. Read below for more info on the production configuration.

In production, the config file that gets loaded is production.json, it gets figured out by the selectconfig grunt task and maps the 'dist' keyword as for production deployment. Note that if you want to know which config will be loaded, have a look at the grunttasks/selectconfig.js file.

Download

curl -o fxa-content-server.tar.gz https://codeload.github.com/webplatform/fxa-content-server/tar.gz/webplatform-customizations
tar xfz fxa-content-server.tar.gz 

Config server/config/production.json:

{
  "env": "production",
  "port": 3030,
  "static_directory": "dist",
  "page_template_subdirectory": "dist",
  "public_url": "https://accounts.webplatform.org",
  "fxaccount_url": "https://api.accounts.webplatform.org",
  "oauth_url": "https://oauth.accounts.webplatform.org",
  "client_sessions": {
    "secret": "...secret...sauce..."
  }
}

Start command:

grunt server:dist

fxa-auth-server

Download

curl -o fxa-auth-server.tar.gz https://codeload.github.com/webplatform/fxa-auth-server/tar.gz/webplatform-customizations
tar xfz fxa-auth-server.tar.gz 

Config config/prod.json:

{
  "env": "prod",
  "listen": {
    "port": 9000
  },
  "contentServer": {
    "url": "https://accounts.webplatform.org"
  },
  "templateServer": {
    "url": "https://accounts.webplatform.org"
  },
  "publicUrl": "https://api.accounts.webplatform.org",
  "smtp": {
    "host": "mail.webplatform.org",
    "port": 25,
    "sender": "WebPlatform Accounts manager <notifier-docs@webplatform.org>",
    "redirectDomain": "webplatform.org"
  },
  "db": {
    "backend": "mysql"
  },
  "mysql": {
    "master": {
      "user": "accounts",
      "password": "...secret...",
      "database": "accounts",
      "host": "db4.dho.wpdn"
    },
    "slave": {
      "user": "accounts",
      "password": "...secret...",
      "database": "accounts",
      "host": "db4.dho.wpdn"
    }
  },
  "log": {
    "level": "debug"
  },
  "verifierVersion": 0,
  "bounces": {
    "region": "us-east-1"
  },
  "customsUrl": "none"
}

Start command:

Create configuration file in config/prod.json, then start in production mode.

sudo CONFIG_FILES=./config/prod.json scripts/start-local.sh 2>&1 | bunyan -o short

fxa-oauth-server

Download

curl -o fxa-oauth-server.tar.gz https://codeload.github.com/webplatform/fxa-oauth-server/tar.gz/master
tar xfz fxa-oauth-server.tar.gz

Config config/prod.json:

{
  "env": "prod",
  "contentUrl": "https://accounts.webplatform.org/oauth/",
  "publicUrl": "https://oauth.accounts.webplatform.org",
  "browserid": {
    "issuer": "api.accounts.webplatform.org",
    "verificationUrl": "https://verifier.accounts.firefox.com/verify"
  },
  "server": {
    "port": 9010
  },
  "db": {
    "driver": "mysql"
  },
  "mysql": {
    "user": "accounts",
    "password": "...password...",
    "database": "accounts_oauth",
    "host": "db4.dho.wpdn"
  },
  "clients": [
    {
      "name": "Temporary 123done",
      "id": "dcdb5ae7add825da",
      "secret": "...private",
      "imageUri": "https://mozorg.cdn.mozilla.net/media/img/firefox/new/header-firefox.png",
      "redirectUri": "https://temporary.webplatform.org/api/oauth",
      "whitelisted": true
    },{
      "name": "WebPlatform Docs",
      "id": "7727862c219a4eb3",
      "secret": "...private",
      "imageUri": "https://webplatformhome.global.ssl.fastly.net/logo/logo-with-text.png",
      "redirectUri": "http://docs.webplatform.org/wiki/Special:OAuth2Client/callback",
      "whitelisted": true
    },{
      "name": "WebPlatform Notes",
      "id": "aa1289c292b0757e",
      "secret": "...private",
      "imageUri": "https://mozorg.cdn.mozilla.net/media/img/firefox/new/header-firefox.png",
      "redirectUri": "https://temporary.webplatform.org/api/oauth",
      "whitelisted": true
    },{
      "name": "RunScope Testbed",
      "id": "398b0cfbe7d86a4a",
      "secret": "...private",
      "imageUri": "https://webplatformhome.global.ssl.fastly.net/logo/logo-with-text.png",
      "redirectUri": "https://www.runscope.com/oauth_tool/callback"
    }
  ],
  "logging": {
    "handlers": {
      "console": {
        "formatter": "pretty"
      }   
    },  
    "loggers": {
      "fxa": {
        "level": "info"
      }   
    }   
  }
}

Start command

CONFIG_FILES=config/prod.json NODE_ENV=prod grunt server 2>&1 | bunyan -o short

fxa-profile-server

Download

curl -o fxa-profile-server.tar.gz https://codeload.github.com/webplatform/fxa-profile-server/tar.gz/master
tar xfz fxa-profile-server.tar.gz
cd fxa-profile-server-webplatform-customizations

Config config/prod.json:

{
  "env": "prod",
  "publicUrl": "https://ssl.webplatform.org",
  "server": {
    "host": "10.0.0.35",
    "port": "8081"
  },
  "db": {
    "driver": "mysql"
  },
  "mysql": {
    "user": "accounts",
    "password": "...secret",
    "database": "accounts",
    "host": "db4.dho.wpdn"
  },
  "oauth": {
    "url": "https://oauth.accounts.webplatform.org/v1"
  },
  "log": {
    "level": "info"
  }
}

Start the server

CONFIG_FILES=config/prod.json NODE_ENV=prod grunt server:dist

Other related notes

123done

An example webapp to test.

Config:

cat config.json 
{
  "client_id": "dcdb5ae7add825da",
  "client_secret": "...private",
  "redirect_uri": "https://temporary.webplatform.org/api/oauth",
  "auth_uri": "https://oauth.accounts.webplatform.org/v1/authorization",
  "oauth_uri": "https://oauth.accounts.webplatform.org/v1",
  "profile_uri": "https://ssl.webplatform.org/v1",
  "scopes": "profile"
}

Start command:

nodejs server.js

Alternate environment management method

Create as much environments as you need (e.g. testing smtp relay), that you can source and run.

environment.mailtrap.txt

NODE_ENV=prod
CONTENT_SERVER_URL=https://accounts.webplatform.org
PUBLIC_URL=https://api.accounts.webplatform.org
DB_BACKEND=mysql
MYSQL_USERNAME=fxauser
MYSQL_PASSWORD=...
MYSQL_DATABASE=fxa_auth
MYSQL_HOST=10.0.0.22
MYSQL_SLAVE_USERNAME=fxauser
MYSQL_SLAVE_PASSWORD=...
MYSQL_SLAVE_DATABASE=fxa_auth
MYSQL_SLAVE_HOST=10.0.0.22
SMTP_SENDER=hostmaster@webplatform.org
SMTP_PORT=25
SMTP_SECURE=false
SMTP_HOST=mailtrap.io
SMTP_USER=...
SMTP_PASS=...

Then source+execute it:

export `cat environment.mailtrap.txt | tr '\n' ' '` ; sudo -E npm start

Creating OAuth client keys

Contributed to Mozilla's OAuth client documentation

In a few lines, using NodeJS command line:

nodejs
var crypto = require('crypto');
var tempGenerator = function(len){ return crypto.randomBytes(Math.ceil(len * 2)).toString('hex').slice(0,len * 2); }; // Bytes aren’t number of characters

Generate an 8-byte id:

tempGenerator(8)
// '4a60bf43fc311d19'

Client secret:

tempGenerator(32)
// 'b048895cbc44241bd68b18ab7d34d1aef8ba34441877ef96c28c706fc1e096fc'

Idea: Convert user accounts from MediaWiki into FxA

Read accounts from MediaWiki

Extract fields, see [#Query from MediaWiki formatted for FxA], for formatting:

SELECT 
    CONVERT(user_name USING utf8) as username,
    CONVERT(user_real_name USING utf8) as fullName,
    CONVERT(user_email USING utf8) as email,
    CONVERT(user_registration, DATETIME) AS createdAt
FROM 
    user;

Attempting to retrieve passwords

This part has been dropped

SELECT 
    CONVERT(user_name USING utf8) as username,
    CONVERT(user_real_name USING utf8) as fullName,
    CONVERT(user_email USING utf8) as email,
    SUBSTRING_INDEX(CONVERT(user_password USING utf8), ':', -1) AS pw_string,
    REPLACE(SUBSTRING_INDEX(CONVERT(user_password USING utf8), ':', 3), ':B:', '') AS pw_salt,
    CONVERT(user_password USING utf8) AS pw_full
FROM 
    user;

Query from MediaWiki formatted for FxA

SELECT 
  CONVERT(user_name USING utf8) as username,
  CONVERT(user_real_name USING utf8) as fullName,
  CONVERT(user_email USING utf8) as email,
  CONVERT(user_email USING utf8) as normalizedEmail,
  CONVERT(user_registration, DATETIME) AS createdAt
FROM 
	user
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment