-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathFB4D.OAuth.pas
122 lines (108 loc) · 4 KB
/
FB4D.OAuth.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
{******************************************************************************}
{ }
{ Delphi FB4D Library }
{ Copyright (c) 2018-2020 Christoph Schneider }
{ Schneider Infosystems AG, Switzerland }
{ https://github.com/SchneiderInfosystems/FB4D }
{ }
{******************************************************************************}
{ }
{ Licensed under the Apache License, Version 2.0 (the "License"); }
{ you may not use this file except in compliance with the License. }
{ You may obtain a copy of the License at }
{ }
{ http://www.apache.org/licenses/LICENSE-2.0 }
{ }
{ Unless required by applicable law or agreed to in writing, software }
{ distributed under the License is distributed on an "AS IS" BASIS, }
{ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. }
{ See the License for the specific language governing permissions and }
{ limitations under the License. }
{ }
{******************************************************************************}
unit FB4D.OAuth;
interface
uses
System.Classes, System.SysUtils, System.Types,
System.JSON, System.JSON.Types,
REST.Types,
JOSE.Types.Bytes, JOSE.Context, JOSE.Core.JWT,
FB4D.Interfaces;
type
TTokenJWT = class(TInterfacedObject, ITokenJWT)
private
fContext: TJOSEContext;
function GetPublicKey(const Id: string): TJOSEBytes;
public
constructor Create(const OAuthToken: string);
destructor Destroy; override;
function VerifySignature: boolean;
function GetHeader: TJWTHeader;
function GetClaims: TJWTClaims;
end;
implementation
uses
System.Generics.Collections,
JOSE.Core.JWS, JOSE.Signing.RSA,
FB4D.Request;
{ TTokenJWT }
constructor TTokenJWT.Create(const OAuthToken: string);
var
CompactToken: TJOSEBytes;
begin
CompactToken.AsString := OAuthToken;
fContext := TJOSEContext.Create(CompactToken, TJWTClaims);
end;
destructor TTokenJWT.Destroy;
begin
fContext.Free;
inherited;
end;
function TTokenJWT.GetPublicKey(const Id: string): TJOSEBytes;
const
GOOGLE_x509 = 'https://www.googleapis.com/robot/v1/metadata/x509';
SToken = '[email protected]';
var
ARequest: TFirebaseRequest;
AResponse: IFirebaseResponse;
JSONObj: TJSONObject;
c: integer;
begin
result.Empty;
ARequest := TFirebaseRequest.Create(GOOGLE_x509, 'GetPublicKey');
JSONObj := nil;
try
AResponse := ARequest.SendRequestSynchronous([SToken], rmGet, nil, nil,
tmNoToken);
JSONObj := TJSONObject.ParseJSONValue(AResponse.ContentAsString) as
TJSONObject;
for c := 0 to JSONObj.Count-1 do
if SameText(JSONObj.Pairs[c].JsonString.Value, Id) then
result.AsString := JSONObj.Pairs[c].JsonValue.Value;
if result.IsEmpty then
raise ETokenJWT.Create('kid not found: ' + Id);
finally
JSONObj.Free;
AResponse := nil;
ARequest.Free;
end;
end;
function TTokenJWT.GetClaims: TJWTClaims;
begin
result := fContext.GetClaims;
end;
function TTokenJWT.GetHeader: TJWTHeader;
begin
result := fContext.GetHeader;
end;
function TTokenJWT.VerifySignature: boolean;
var
PublicKey: TJOSEBytes;
jws: TJWS;
begin
jws := fContext.GetJOSEObject<TJWS>;
PublicKey := GetPublicKey(GetHeader.JSON.GetValue('kid').Value);
jws.SetKey(PublicKey);
result := jws.VerifySignature;
end;
end.