Skip to content

Commit

Permalink
feat(auth): switching OpenID Connect provider to Google for API
Browse files Browse the repository at this point in the history
  • Loading branch information
xmlking committed May 4, 2019
1 parent e5d052a commit eff9ad5
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 54 deletions.
16 changes: 14 additions & 2 deletions .deploy/keycloak/helm/values.yaml
Expand Up @@ -11,7 +11,7 @@ keycloak:

image:
repository: jboss/keycloak
tag: 4.8.3.Final
tag: 5.0.0
pullPolicy: IfNotPresent

## Optionally specify an array of imagePullSecrets.
Expand Down Expand Up @@ -43,16 +43,28 @@ keycloak:
## Custom script that is run before Keycloak is started.
preStartScript:

## lifecycleHooks defines the container lifecycle hooks
lifecycleHooks: |
# postStart:
# exec:
# command: ["/bin/sh", "-c", "ls"]
## Additional arguments to start command e.g. -Dkeycloak.import= to load a realm
extraArgs: ""

## Username for the initial Keycloak admin user
username: keycloak

## Password for the initial Keycloak admin user
## Password for the initial Keycloak admin user. Applicable only if existingSecret is not set.
## If not set, a random 10 characters password will be used
password: ""

# Specifies an existing secret to be used for the admin password
existingSecret: ""

# The key in the existing secret that stores the password
existingSecretKey: password

## Allows the specification of additional environment variables for Keycloak
extraEnv: |
# - name: KEYCLOAK_LOGLEVEL
Expand Down
6 changes: 5 additions & 1 deletion .deploy/postgres/helm/README.md
Expand Up @@ -25,7 +25,7 @@ helm ls
helm ls -a --tiller-namespace=kube-system --debug

# To uninstall/delete the postgres deployment:
helm delete --purge postgres
helm delete --purge ngxdb
```

### Without Tiller
Expand All @@ -46,6 +46,10 @@ kubectl apply --recursive -f generated/postgresql/* --namespace default

### Connect to Postgres

PostgreSQL can be accessed via port 5432 on the following DNS name from within your cluster:

ngxdb-postgresql.default.svc.cluster.local - Read/Write connection

To get the password for "postgres" run:

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default ngxdb-postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode)
Expand Down
5 changes: 0 additions & 5 deletions .deploy/postgres/helm/values-dev.yaml
Expand Up @@ -23,8 +23,3 @@ service:
type: NodePort
nodePort: 31432

volumePermissions:
image:
tag: 1.0.0
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
pullPolicy: IfNotPresent
15 changes: 15 additions & 0 deletions angular.json
Expand Up @@ -252,6 +252,18 @@
"with": "apps/api/src/environments/environment.prod.ts"
}
]
},
"mock": {
"sourceMap": false,
"optimization": true,
"extractLicenses": true,
"inspect": false,
"fileReplacements": [
{
"replace": "apps/api/src/environments/environment.ts",
"with": "apps/api/src/environments/environment.mock.ts"
}
]
}
}
},
Expand All @@ -263,6 +275,9 @@
"configurations": {
"production": {
"buildTarget": "api:build:production"
},
"mock": {
"buildTarget": "api:build:mock"
}
}
},
Expand Down
28 changes: 22 additions & 6 deletions apps/api/src/app/config/config.service.ts
@@ -1,23 +1,25 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { environment } from '@env-api/environment';
import { IEnvironment } from '../../environments/ienvironment';
import axios from 'axios';

// tslint:disable-next-line
const packageJson = require('../../../../../package.json');

@Injectable()
export class ConfigService {
private readonly config;
private readonly logger = new Logger(ConfigService.name);
private readonly config = environment;

constructor() {
this.config = environment;
for (const [key, value] of Object.entries(environment.env)) {
process.env[key] = value ;
process.env[key] = value;
}
console.log('is prod? ', environment.production);
}

get(key: string): any {
return this.config.get(key);
get(key: keyof IEnvironment): IEnvironment[keyof IEnvironment] {
return this.config[key];
}

getVersion(): string {
Expand All @@ -34,4 +36,18 @@ export class ConfigService {
getAllowWhitelist(): string[] {
return this.config.ALLOW_WHITE_LIST ? this.config.ALLOW_WHITE_LIST : [];
}

async getOpenIdConfiguration() {
try {
const response = await axios.get(`${this.config.auth.issuer}/.well-known/openid-configuration`);
return response.data;
} catch (err) {
this.logger.error(`Unable to fetch config from ${this.config.auth.issuer}/.well-known/openid-configuration, \nError: ${err}`);
this.logger.error('Check if Oauth Server is UP');
}
}

getAuth() {
return this.config.auth;
}
}
67 changes: 67 additions & 0 deletions apps/api/src/environments/environment.mock.ts
@@ -0,0 +1,67 @@
import { IEnvironment } from './ienvironment';

export const environment: IEnvironment = {
production: true,
envName: 'mock',

env: {
NODE_TLS_REJECT_UNAUTHORIZED: '0',
},

server: {
host: process.env.HOST || '0.0.0.0',
domainUrl: process.env.DOMAIN_URL || 'http://localhost:3000',
port: process.env.PORT || 3000,
globalPrefix: '/api',
},

database: {
type: 'postgres',
host: process.env.TYPEORM_HOST || 'localhost',
port: process.env.TYPEORM_PORT ? Number(process.env.TYPEORM_PORT) : 31432,
database: process.env.TYPEORM_DATABASE || 'postgres',
username: process.env.TYPEORM_USERNAME || 'postgres',
password: process.env.TYPEORM_PASSWORD || 'postgres321',
keepConnectionAlive: true,
logging: process.env.TYPEORM_LOGGING ? JSON.parse(process.env.TYPEORM_LOGGING) : false,
synchronize: false,
uuidExtension: 'pgcrypto',
},

auth: {
clientId: process.env.OIDC_CLIENT_ID || '791772336084-vkt37abstm1du92ofdmhgi30vgd7t0oa.apps.googleusercontent.com',
issuer: process.env.OIDC_ISSUER_URL || 'https://accounts.google.com',
jwksUri: process.env.OIDC_JWKS_URL || 'https://www.googleapis.com/oauth2/v3/certs',
additionalQueryStringParams: { scope: 'openid profile email' }
},

email: {
transport: {
host: process.env.EMAIL_HOST || 'mail.google.com',
port: process.env.EMAIL_PORT ? Number(process.env.EMAIL_PORT) : 25,
secure: process.env.EMAIL_SECURE ? JSON.parse(process.env.EMAIL_SECURE) : false,
auth: {
user: process.env.EMAIL_AUTH_USER || 'auth_user',
pass: process.env.EMAIL_AUTH_PASS || 'auth_pass',
},
},
defaults: {
from: process.env.EMAIL_FROM ? process.env.EMAIL_FROM : '"sumo demo" <sumo@demo.com>',
},
templateDir: 'apps/api/src/assets/email-templates',
},

weather: {
baseUrl: 'https://api.openweathermap.org/data/2.5',
apiKey: '7cb0f6a068d1de4845c49ba22b74d7cc',
},

// Key generation: https://web-push-codelab.glitch.me
webPush: {
subject: process.env.VAPID_SUBJECT || 'mailto: sumo@demo.com',
publicKey:
process.env.VAPID_PUBLIC_KEY ||
'BAJq-yHlSNjUqKW9iMY0hG96X9WdVwetUFDa5rQIGRPqOHKAL_fkKUe_gUTAKnn9IPAltqmlNO2OkJrjdQ_MXNg',
privateKey: process.env.VAPID_PRIVATE_KEY || 'cwh2CYK5h_B_Gobnv8Ym9x61B3qFE2nTeb9BeiZbtMI',
},
};
4 changes: 2 additions & 2 deletions apps/api/src/environments/environment.ts
Expand Up @@ -36,8 +36,8 @@ export const environment: IEnvironment = {

auth: {
clientId: 'ngxapi',
// issuer: 'http://localhost:8080/auth/realms/ngx',
issuer: 'https://keycloak-ngx1.1d35.starter-us-east-1.openshiftapps.com/auth/realms/ngx',
issuer: 'https://keycloak.traefik.k8s/auth/realms/ngx',
// additionalQueryStringParams: { scope: 'openid profile email', nonce: '1234578910' }
},

email: {
Expand Down
6 changes: 6 additions & 0 deletions apps/api/src/environments/ienvironment.ts
Expand Up @@ -34,6 +34,12 @@ export interface IEnvironment {
clientId: string;
issuer: string;
jwksUri?: string;
additionalQueryStringParams?: Partial<{
scope: string;
nonce: string;
audience: string
[key: string]: string
}>;
};

email: EmailModuleOptions;
Expand Down
16 changes: 14 additions & 2 deletions apps/api/src/main.hmr.ts
Expand Up @@ -5,6 +5,7 @@ import { AppModule } from './app/app.module';
import { ConfigService } from './app/config';
import * as helmet from 'helmet';
import { environment as env } from '@env-api/environment';
import { useContainer } from 'class-validator';

declare const module: any;

Expand All @@ -22,6 +23,13 @@ async function bootstrap() {
}),
);

// Link DI container to class-validator
useContainer(app.select(AppModule), { fallbackOnErrors: true });

// for uploaded images
// app.useStaticAssets(join(__dirname, './../public'));

const openIdConf = await config.getOpenIdConfiguration();
const options = new DocumentBuilder()
.setTitle('Sumo API Docs')
.setDescription('Sumo API for Ngx Starter Kit')
Expand All @@ -30,17 +38,21 @@ async function bootstrap() {
.setSchemes(config.isProd() ? 'https' : 'http')
.addOAuth2(
'implicit',
`${env.auth.issuer}/protocol/openid-connect/auth`,
`${env.auth.issuer}/protocol/openid-connect/token`,
openIdConf.authorization_endpoint,
openIdConf.token_endpoint,
// {openid: 'openid', profile: 'profile', email: 'email'}
)
.build();
const document = SwaggerModule.createDocument(app, options);
const { additionalQueryStringParams } = config.getAuth();
SwaggerModule.setup('docs', app, document, {
swaggerOptions: {
oauth2RedirectUrl: `${env.server.domainUrl}/docs/oauth2-redirect.html`,
oauth: {
clientId: env.auth.clientId,
appName: 'Sumo API',
// scopeSeparator: ' ',
additionalQueryStringParams,
},
},
});
Expand Down
9 changes: 6 additions & 3 deletions apps/api/src/main.ts
Expand Up @@ -28,6 +28,7 @@ async function bootstrap() {
// for uploaded images
// app.useStaticAssets(join(__dirname, './../public'));

const openIdConf = await config.getOpenIdConfiguration();
const options = new DocumentBuilder()
.setTitle('Sumo API Docs')
.setDescription('Sumo API for Ngx Starter Kit')
Expand All @@ -36,19 +37,21 @@ async function bootstrap() {
.setSchemes(config.isProd() ? 'https' : 'http')
.addOAuth2(
'implicit',
`${env.auth.issuer}/protocol/openid-connect/auth`,
`${env.auth.issuer}/protocol/openid-connect/token`,
openIdConf.authorization_endpoint,
openIdConf.token_endpoint,
// {openid: 'openid', profile: 'profile', email: 'email'}
)
.build();
const document = SwaggerModule.createDocument(app, options);
const { additionalQueryStringParams } = config.getAuth();
SwaggerModule.setup('docs', app, document, {
swaggerOptions: {
oauth2RedirectUrl: `${env.server.domainUrl}/docs/oauth2-redirect.html`,
oauth: {
clientId: env.auth.clientId,
appName: 'Sumo API',
// scopeSeparator: ' ',
// additionalQueryStringParams: {audience: env.oidc.audience},
additionalQueryStringParams,
},
},
});
Expand Down
41 changes: 25 additions & 16 deletions apps/webapp/src/app/app.module.ts
Expand Up @@ -27,26 +27,35 @@ export class MyHammerConfig extends HammerGestureConfig {
RouterModule.forRoot(
[
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'home',
loadChildren: () => import('@ngx-starter-kit/home').then(m => m.HomeModule),
data: { preload: true },
},
{
path: 'dashboard',
loadChildren: () => import('@ngx-starter-kit/dashboard').then(m => m.DashboardModule),
data: { preload: true },
},
{
path: 'admin',
loadChildren: () => import('@ngx-starter-kit/admin').then(m => m.AdminModule),
data: { preload: false },
},
{ path: 'home', loadChildren: '@ngx-starter-kit/home#HomeModule', data: { preload: true } },
{ path: 'dashboard', loadChildren: '@ngx-starter-kit/dashboard#DashboardModule', data: { preload: true } },
{ path: 'admin', loadChildren: '@ngx-starter-kit/admin#AdminModule', data: { preload: false } },
{
path: '404',
loadChildren: () => import('@ngx-starter-kit/not-found').then(m => m.NotFoundModule),
loadChildren: '@ngx-starter-kit/not-found#NotFoundModule',
data: { title: '404', preload: false },
},
// TODO: uncomment after Ivy
// {
// path: 'home',
// loadChildren: () => import('@ngx-starter-kit/home').then(m => m.HomeModule),
// data: { preload: true },
// },
// {
// path: 'dashboard',
// loadChildren: () => import('@ngx-starter-kit/dashboard').then(m => m.DashboardModule),
// data: { preload: true },
// },
// {
// path: 'admin',
// loadChildren: () => import('@ngx-starter-kit/admin').then(m => m.AdminModule),
// data: { preload: false },
// },
// {
// path: '404',
// loadChildren: () => import('@ngx-starter-kit/not-found').then(m => m.NotFoundModule),
// data: { title: '404', preload: false },
// },
// 404 should be last
{ path: '**', redirectTo: '404', pathMatch: 'full' },
],
Expand Down
6 changes: 4 additions & 2 deletions apps/webapp/src/environments/environment.mock.ts
Expand Up @@ -11,7 +11,9 @@ export const environment: IEnvironment = {
WS_EVENT_BUS_URL: 'ws://localhost:3000/eventbus',

auth: {
clientId: 'ngxweb',
issuer: 'https://keycloak-ngx1.1d35.starter-us-east-1.openshiftapps.com/auth/realms/ngx',
// clientId: 'ngxweb',
// issuer: 'https://keycloak.traefik.k8s/auth/realms/ngx',
clientId: '791772336084-vkt37abstm1du92ofdmhgi30vgd7t0oa.apps.googleusercontent.com',
issuer: 'https://accounts.google.com'
},
};
10 changes: 4 additions & 6 deletions apps/webapp/src/environments/environment.ts
Expand Up @@ -14,12 +14,10 @@ export const environment: IEnvironment = {
WS_EVENT_BUS_URL: 'ws://localhost:3000/eventbus',

auth: {
// clientId: 'ngxweb',
// // issuer: 'http://localhost:8080/auth/realms/ngx',
// issuer: 'https://keycloak-ngx1.1d35.starter-us-east-1.openshiftapps.com/auth/realms/ngx',

clientId: '791772336084-vkt37abstm1du92ofdmhgi30vgd7t0oa.apps.googleusercontent.com',
issuer: 'https://accounts.google.com'
clientId: 'ngxweb',
issuer: 'https://keycloak.traefik.k8s/auth/realms/ngx',
// clientId: '791772336084-vkt37abstm1du92ofdmhgi30vgd7t0oa.apps.googleusercontent.com',
// issuer: 'https://accounts.google.com'
},
};

Expand Down

0 comments on commit eff9ad5

Please sign in to comment.