11import * as OAuthServer from "oauth2-server" ;
22import * as winston from "winston" ;
33import * as express from "express" ;
4- import { TokenUser } from "openflow-api" ;
4+ import { TokenUser , Base } from "openflow-api" ;
5+ import { Config } from "./Config" ;
6+ import { Crypt } from "./Crypt" ;
57const Request = OAuthServer . Request ;
68const Response = OAuthServer . Response ;
79export class OAuthProvider {
810 private _logger : winston . Logger ;
911 private app : express . Express ;
1012 public static instance : OAuthProvider = null ;
11- private clients = [ {
12- id : 'application' , // TODO: Needed by refresh_token grant, because there is a bug at line 103 in https://github.com/oauthjs/node-oauth2-server/blob/v3.0.1/lib/grant-types/refresh-token-grant-type.js (used client.id instead of client.clientId)
13- clientId : 'application' ,
14- clientSecret : 'secret' ,
15- grants : [
16- 'password' ,
17- 'refresh_token' ,
18- 'authorization_code'
19- ] ,
20- redirectUris : [ ]
21- } ] ;
13+ // private clients = [{
14+ // id: 'application', // TODO: Needed by refresh_token grant, because there is a bug at line 103 in https://github.com/oauthjs/node-oauth2-server/blob/v3.0.1/lib/grant-types/refresh-token-grant-type.js (used client.id instead of client.clientId)
15+ // clientId: 'application',
16+ // clientSecret: 'secret',
17+ // grants: [
18+ // 'password',
19+ // 'refresh_token',
20+ // 'authorization_code'
21+ // ],
22+ // redirectUris: []
23+ // }];
24+ private clients = [ ] ;
2225 private tokens = [ ] ;
2326 private codes = { } ;
2427 public oauthServer : any = null ;
@@ -39,25 +42,31 @@ export class OAuthProvider {
3942 } ) ;
4043 ( app as any ) . oauth = instance . oauthServer ;
4144 app . all ( '/oauth/token' , instance . obtainToken . bind ( instance ) ) ;
42- app . get ( '/oauth/login' , ( req , res ) => {
45+ app . get ( '/oauth/login' , async ( req , res ) => {
46+ instance . clients = await Config . db . query < Base > ( { _type : "oauthclient" } , null , 10 , 0 , null , "config" , Crypt . rootToken ( ) ) ;
47+ if ( instance . clients == null || instance . clients . length == 0 ) return res . status ( 500 ) . json ( { message : 'OAuth not configured' } ) ;
4348 let state = req . params . state ;
4449 if ( state == null ) state = encodeURIComponent ( req . query . state as any ) ;
4550 const access_type = req . query . access_type ;
4651 const client_id = req . query . client_id ;
4752 const redirect_uri = req . query . redirect_uri ;
4853 const response_type = req . query . response_type ;
4954 const scope = req . query . scope ;
55+ let client = instance . getClientById ( client_id ) ;
5056 if ( req . user ) {
51- // TODO: Add logic for configurering redirect url's !!!!!!!!
52- if ( instance . clients [ 0 ] . redirectUris . indexOf ( redirect_uri ) == - 1 ) {
53- instance . clients [ 0 ] . redirectUris . push ( redirect_uri ) ;
57+ if ( client . redirectUris . length > 0 ) {
58+ if ( client . redirectUris . indexOf ( redirect_uri ) == - 1 ) {
59+ return res . status ( 500 ) . json ( { message : 'illegal redirect_uri ' + redirect_uri } ) ;
60+ // client.redirectUris.push(redirect_uri);
61+ }
5462 }
63+ const code = Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) ;
5564
5665 instance . _logger . info ( "[OAuth][" + ( req . user as any ) . username + "] /oauth/login " + state ) ;
57- instance . codes [ "cc536d98d27750394a87ab9d057016e636a8ac31" ] = req . user ;
58- instance . codes [ "cc536d98d27750394a87ab9d057016e636a8ac31" ] . redirect_uri = redirect_uri ;
59- // res.redirect(`${GRAFANA_URI}/login/generic_oauth?state=${state}& code=cc536d98d27750394a87ab9d057016e636a8ac31`) ;
60- res . redirect ( `${ redirect_uri } ?state=${ state } &code=cc536d98d27750394a87ab9d057016e636a8ac31 ` ) ;
66+ instance . codes [ code ] = req . user ;
67+ instance . codes [ code ] . redirect_uri = redirect_uri ;
68+ instance . codes [ code ] . client_id = client_id ;
69+ res . redirect ( `${ redirect_uri } ?state=${ state } &code=${ code } ` ) ;
6170 } else {
6271 instance . _logger . info ( "[OAuth][anon] /oauth/login " + state ) ;
6372 res . cookie ( "originalUrl" , req . originalUrl , { maxAge : 900000 , httpOnly : true } ) ;
@@ -126,18 +135,14 @@ export class OAuthProvider {
126135 res . status ( err . code || 500 ) . json ( err ) ;
127136 } ) ;
128137 }
129- public getAccessToken ( bearerToken ) {
138+ public async getAccessToken ( bearerToken ) {
130139 this . _logger . info ( "[OAuth] getAccessToken " + bearerToken ) ;
131- const tokens = this . tokens . filter ( ( token ) => {
132- return token . accessToken === bearerToken ;
133- } ) ;
140+ const tokens = await Config . db . query < Base > ( { _type : "token" , "accessToken" : bearerToken } , null , 10 , 0 , null , "oauthtokens" , Crypt . rootToken ( ) ) ;
134141 return tokens . length ? tokens [ 0 ] : false ;
135142 }
136- public getRefreshToken ( bearerToken ) {
143+ public async getRefreshToken ( bearerToken ) {
137144 this . _logger . info ( "[OAuth] getRefreshToken " + bearerToken ) ;
138- const tokens = this . tokens . filter ( ( token ) => {
139- return token . refreshToken === bearerToken ;
140- } ) ;
145+ const tokens = await Config . db . query < Base > ( { _type : "token" , "refreshToken" : bearerToken } , null , 10 , 0 , null , "oauthtokens" , Crypt . rootToken ( ) ) ;
141146 return tokens . length ? tokens [ 0 ] : false ;
142147 }
143148 public getClient ( clientId , clientSecret ) {
@@ -147,9 +152,17 @@ export class OAuthProvider {
147152 } ) ;
148153 return clients . length ? clients [ 0 ] : false ;
149154 }
150- public saveToken ( token , client , user ) {
155+ public getClientById ( clientId ) {
156+ this . _logger . info ( "[OAuth] getClientById " + clientId ) ;
157+ const clients = this . clients . filter ( ( client ) => {
158+ return client . clientId === clientId ;
159+ } ) ;
160+ return clients . length ? clients [ 0 ] : false ;
161+ }
162+
163+ public async saveToken ( token , client , user ) {
151164 this . _logger . info ( "[OAuth] saveToken " + token ) ;
152- const result = {
165+ const result : any = {
153166 accessToken : token . accessToken ,
154167 access_token : token . accessToken ,
155168 accessTokenExpiresAt : token . accessTokenExpiresAt ,
@@ -158,43 +171,50 @@ export class OAuthProvider {
158171 refresh_token : token . refreshToken ,
159172 refreshTokenExpiresAt : token . refreshTokenExpiresAt ,
160173 userId : user . id ,
161-
162174 user : user ,
163- client : this . clients [ 0 ]
175+ client : client ,
176+ _type : "token"
164177 } ;
165178 this . tokens . push ( result ) ;
179+ await Config . db . InsertOne ( result , "oauthtokens" , 0 , false , Crypt . rootToken ( ) ) ;
166180 return result ;
167181 }
168182 saveAuthorizationCode ( code , client , user ) {
169183 this . _logger . info ( "[OAuth] saveAuthorizationCode " + code ) ;
170- // const codeToSave: any = this.codes[code];
171- const codeToSave : any = {
172- 'authorizationCode' : code . authorizationCode ,
173- 'expiresAt' : code . expiresAt ,
174- 'redirectUri' : code . redirectUri ,
175- 'scope' : code . scope ,
176- 'client' : client . id ,
177- 'user' : user . username
178- } ;
179- this . codes [ code ] = codeToSave ;
180- code = Object . assign ( { } , code , {
181- 'client' : client . id ,
182- 'user' : user . username
183- } ) ;
184+ // // const codeToSave: any = this.codes[code];
185+ // const codeToSave: any = {
186+ // 'authorizationCode': code.authorizationCode,
187+ // 'expiresAt': code.expiresAt,
188+ // 'redirectUri': code.redirectUri,
189+ // 'scope': code.scope,
190+ // 'client': client.id,
191+ // 'user': user.username
192+ // };
193+ // this.codes[code] = codeToSave;
194+ // this.revokeAuthorizationCode(code);
195+ // code = Object.assign({}, code, {
196+ // 'client': client.id,
197+ // 'user': user.username
198+ // });
184199 return code ;
185200 }
186201 getAuthorizationCode ( code ) {
187202 this . _logger . info ( "[OAuth] getAuthorizationCode " + code ) ;
188203 let user : TokenUser = this . codes [ code ] ;
204+ const client_id : string = this . codes [ code ] . client_id ;
189205 if ( user == null ) return null ;
206+ this . revokeAuthorizationCode ( code ) ;
190207 const redirect_uri = ( user as any ) . redirect_uri ;
191208 const expiresAt = new Date ( ) ;
192209 expiresAt . setMonth ( expiresAt . getMonth ( ) + 1 ) ;
193- let role = "Viewer" ;
194210 user = TokenUser . From ( user ) ;
195- if ( user . HasRoleName ( "admins" ) ) role = "Admin" ;
196- if ( user . HasRoleName ( "grafana editors" ) ) role = "Editor" ;
197- if ( user . HasRoleName ( "grafana admins" ) ) role = "Admin" ;
211+ let client = this . getClientById ( client_id ) ;
212+
213+ let role = client . defaultrole ;
214+ const keys : string [ ] = Object . keys ( client . rolemappings ) ;
215+ for ( let i = 0 ; i < keys . length ; i ++ ) {
216+ if ( user . HasRoleName ( keys [ i ] ) ) role = client . rolemappings [ keys [ i ] ] ;
217+ }
198218 const result = {
199219 code : code ,
200220 client : this . clients [ 0 ] ,
@@ -209,12 +229,11 @@ export class OAuthProvider {
209229 expiresAt : expiresAt ,
210230 redirectUri : redirect_uri
211231 }
212- // Viewer, Editor, Admin
213- // return result;
214232 return result ;
215233 }
216234 revokeAuthorizationCode ( code ) {
217235 this . _logger . info ( "[OAuth] revokeAuthorizationCode " + code ) ;
236+ delete this . codes [ code ] ;
218237 return true ;
219238 // const user: TokenUser = this.codes[code];
220239 // if (user != null) delete this.codes[code];
0 commit comments