├── package.cmd ├── packages ├── JWT.1.3.1 │ └── lib │ │ └── 3.5 │ │ └── JWT.dll └── repositories.config ├── FirebaseTokenGenerator ├── packages.config ├── TokenOptions.cs ├── Properties │ └── AssemblyInfo.cs ├── FirebaseTokenGenerator.csproj └── TokenGenerator.cs ├── .gitattributes ├── FirebaseTokenGenerator.nuspec ├── LICENSE ├── FirebaseTokenGenerator.Tests ├── Properties │ └── AssemblyInfo.cs ├── FirebaseTokenGenerator.Tests.csproj └── BasicUnitTest.cs ├── FirebaseTokenGenerator.sln ├── .gitignore └── README.md /package.cmd: -------------------------------------------------------------------------------- 1 | nuget update -self 2 | nuget pack FirebaseTokenGenerator\FirebaseTokenGenerator.csproj 3 | -------------------------------------------------------------------------------- /packages/JWT.1.3.1/lib/3.5/JWT.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googlearchive/firebase-token-generator-dotNet/HEAD/packages/JWT.1.3.1/lib/3.5/JWT.dll -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FirebaseTokenGenerator 5 | $version$ 6 | Firebase Token Generator 7 | $author$ 8 | $author$ 9 | http://firebase.mit-license.org/ 10 | https://github.com/firebase/firebase-token-generator-dotNet 11 | false 12 | $description$ 13 | Copyright 2014 14 | firebase token jwt security authentication 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2014 Firebase 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator/TokenOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Firebase 7 | { 8 | public class TokenOptions 9 | { 10 | public DateTime? expires { get; private set; } 11 | public DateTime? notBefore { get; private set; } 12 | public bool admin { get; private set; } 13 | public bool debug { get; private set; } 14 | 15 | /// 16 | /// Constructor. All options are optional. 17 | /// 18 | /// The date/time before which the token should not be considered valid. (default is now) 19 | /// The date/time at which the token should no longer be considered valid. (default is 24 hours from now) 20 | /// Set to true to bypass all security rules. (you can use this for trusted server code) 21 | /// Set to true to enable debug mode. (so you can see the results of Rules API operations) 22 | public TokenOptions(DateTime? notBefore = null, DateTime? expires = null, bool admin = false, bool debug = false) 23 | { 24 | this.notBefore = notBefore; 25 | this.expires = expires; 26 | this.admin = admin; 27 | this.debug = debug; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FirebaseTokenGenerator.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("FirebaseTokenGenerator.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8e346b3e-2110-45c5-b287-3ff8d30baff1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FirebaseTokenGenerator")] 9 | [assembly: AssemblyDescription("Firebase Token Generator for .Net")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Firebase")] 12 | [assembly: AssemblyProduct("FirebaseTokenGenerator")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e5d72cf8-d4aa-47d4-85d3-7527260dc405")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2.0.0.0")] 36 | [assembly: AssemblyFileVersion("2.0.0.0")] 37 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Web 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirebaseTokenGenerator", "FirebaseTokenGenerator\FirebaseTokenGenerator.csproj", "{EDF6D0EC-8015-463C-9B3B-034EF0F897A9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FirebaseTokenGenerator.Tests", "FirebaseTokenGenerator.Tests\FirebaseTokenGenerator.Tests.csproj", "{40A54324-D081-4C1F-8F39-F2DB4BF20166}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {EDF6D0EC-8015-463C-9B3B-034EF0F897A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {EDF6D0EC-8015-463C-9B3B-034EF0F897A9}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {EDF6D0EC-8015-463C-9B3B-034EF0F897A9}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {EDF6D0EC-8015-463C-9B3B-034EF0F897A9}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {40A54324-D081-4C1F-8F39-F2DB4BF20166}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {40A54324-D081-4C1F-8F39-F2DB4BF20166}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {40A54324-D081-4C1F-8F39-F2DB4BF20166}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {40A54324-D081-4C1F-8F39-F2DB4BF20166}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator/FirebaseTokenGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | AnyCPU 7 | {EDF6D0EC-8015-463C-9B3B-034EF0F897A9} 8 | Library 9 | Properties 10 | FirebaseTokenGenerator 11 | FirebaseTokenGenerator 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | False 35 | ..\packages\JWT.1.3.1\lib\3.5\JWT.dll 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | 165 | # NuGet packages. 166 | *.nupkg 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Status: Archived 2 | This repository has been archived and is no longer maintained. 3 | 4 | ![status: inactive](https://img.shields.io/badge/status-inactive-red.svg) 5 | 6 | # Firebase Token Generator - .NET 7 | 8 | **WARNING: This token generator is compatible with versions 1.x.x and 2.x.x of the Firebase SDK. If you are using the 3.x.x SDK, please refer to the documentation [here](https://firebase.google.com/docs/auth/server#use_a_jwt_library).** 9 | 10 | [Firebase Custom Login](https://www.firebase.com/docs/web/guide/simple-login/custom.html) 11 | gives you complete control over user authentication by allowing you to authenticate users 12 | with secure JSON Web Tokens (JWTs). The auth payload stored in those tokens is available 13 | for use in your Firebase [security rules](https://www.firebase.com/docs/security/api/rule/). 14 | This is a token generator library for .Net which allows you to easily create those JWTs. 15 | 16 | 17 | ## Installation 18 | 19 | The easiest way to install The Firebase .Net token generator is via NuGet. Just search for 20 | "FirebaseTokenGenerator" in NuGet or install it via the Package Manager Console: 21 | 22 | ``` 23 | PM> Install-Package FirebaseTokenGenerator 24 | ``` 25 | 26 | 27 | ## A Note About Security 28 | 29 | **IMPORTANT:** Because token generation requires your Firebase Secret, you should only generate 30 | tokens on *trusted servers*. Never embed your Firebase Secret directly into your application and 31 | never share your Firebase Secret with a connected client. 32 | 33 | 34 | ## Generating Tokens 35 | 36 | To generate tokens, you'll need your Firebase Secret which you can find by entering your Firebase 37 | URL into a browser and clicking the "Secrets" tab on the left-hand navigation menu. 38 | 39 | Once you've downloaded the library and grabbed your Firebase Secret, you can generate a token with 40 | this snippet of .Net code: 41 | 42 | ``` 43 | var tokenGenerator = new Firebase.TokenGenerator(""); 44 | var authPayload = new Dictionary() 45 | { 46 | { "uid", "1" }, 47 | { "some", "arbitrary" }, 48 | { "data", "here" } 49 | }; 50 | string token = tokenGenerator.CreateToken(authPayload); 51 | ``` 52 | 53 | The payload object passed into `CreateToken()` is then available for use within your 54 | security rules via the [`auth` variable](https://www.firebase.com/docs/security/api/rule/auth.html). 55 | This is how you pass trusted authentication details (e.g. the client's user ID) to your 56 | Firebase rules. The payload can contain any data of your choosing, however it 57 | must contain a "uid" key, which must be a string of less than 256 characters. The 58 | generated token must be less than 1024 characters in total. 59 | 60 | 61 | ## Token Options 62 | 63 | A second `options` argument can be passed to `CreateToken()` to modify how Firebase treats the 64 | token. Available options are: 65 | 66 | * **expires** (DateTime) - A timestamp denoting the time after which this token should no longer 67 | be valid. 68 | 69 | * **notBefore** (DateTime) - A timestamp denoting the time before which this token should be 70 | rejected by the server. 71 | 72 | * **admin** (bool) - Set to `true` if you want to disable all security rules for this client. This 73 | will provide the client with read and write access to your entire Firebase. 74 | 75 | * **debug** (bool) - Set to `true` to enable debug output from your security rules. You should 76 | generally *not* leave this set to `true` in production (as it slows down the rules implementation 77 | and gives your users visibility into your rules), but it can be helpful for debugging. 78 | 79 | Here is an example of how to use the second `options` argument: 80 | 81 | ``` 82 | var tokenGenerator = new Firebase.TokenGenerator(""); 83 | var authPayload = new Dictionary() 84 | { 85 | { "uid", "1" }, 86 | { "some", "arbitrary" }, 87 | { "data", "here" } 88 | }; 89 | string token = tokenGenerator.CreateToken(authPayload, new Firebase.TokenOptions(admin: true)); 90 | ``` 91 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator/TokenGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Firebase 7 | { 8 | /// 9 | /// Generates firebase auth tokens for your firebase. 10 | /// 11 | public class TokenGenerator 12 | { 13 | private static int TOKEN_VERSION = 0; 14 | private string _firebaseSecret; 15 | 16 | /// 17 | /// Constructor. 18 | /// 19 | /// The Firebase Secret for your firebase (can be found by entering your Firebase URL into a web browser, and clicking the "Auth" pane). 20 | public TokenGenerator(string firebaseSecret) 21 | { 22 | _firebaseSecret = firebaseSecret; 23 | } 24 | 25 | /// 26 | /// Creates an authentication token containing arbitrary auth data. 27 | /// 28 | /// Arbitrary data that will be passed to the Firebase Rules API, once a client authenticates. Must be able to be serialized to JSON with . 29 | /// The auth token. 30 | public string CreateToken(Dictionary data) 31 | { 32 | return CreateToken(data, new TokenOptions()); 33 | } 34 | 35 | /// 36 | /// Creates an authentication token containing arbitrary auth data and the specified options. 37 | /// 38 | /// Arbitrary data that will be passed to the Firebase Rules API, once a client authenticates. Must be able to be serialized to JSON with . 39 | /// A set of custom options for the token. 40 | /// The auth token. 41 | public string CreateToken(Dictionary data, TokenOptions options) 42 | { 43 | var dataEmpty = (data == null || data.Count == 0); 44 | if (dataEmpty && (options == null || (!options.admin && !options.debug))) 45 | { 46 | throw new Exception("data is empty and no options are set. This token will have no effect on Firebase."); 47 | } 48 | 49 | var claims = new Dictionary(); 50 | claims["v"] = TOKEN_VERSION; 51 | claims["iat"] = secondsSinceEpoch(DateTime.Now); 52 | 53 | var isAdminToken = (options != null && options.admin); 54 | validateToken(data, isAdminToken); 55 | 56 | if (!dataEmpty) 57 | { 58 | claims["d"] = data; 59 | } 60 | 61 | // Handle options. 62 | if (options != null) 63 | { 64 | if (options.expires.HasValue) 65 | claims["exp"] = secondsSinceEpoch(options.expires.Value); 66 | if (options.notBefore.HasValue) 67 | claims["nbf"] = secondsSinceEpoch(options.notBefore.Value); 68 | if (options.admin) 69 | claims["admin"] = true; 70 | if (options.debug) 71 | claims["debug"] = true; 72 | } 73 | 74 | var token = computeToken(claims); 75 | if (token.Length > 1024) 76 | { 77 | throw new Exception("Generated token is too long. The token cannot be longer than 1024 bytes."); 78 | } 79 | return token; 80 | } 81 | 82 | private string computeToken(Dictionary claims) 83 | { 84 | return JWT.JsonWebToken.Encode(claims, this._firebaseSecret, JWT.JwtHashAlgorithm.HS256); 85 | } 86 | 87 | private static long secondsSinceEpoch(DateTime dt) 88 | { 89 | TimeSpan t = dt.ToUniversalTime() - new DateTime(1970, 1, 1); 90 | return (long)t.TotalSeconds; 91 | } 92 | 93 | private static void validateToken(Dictionary data, Boolean isAdminToken) 94 | { 95 | var containsUid = (data != null && data.ContainsKey("uid")); 96 | if ((!containsUid && !isAdminToken) || (containsUid && !(data["uid"] is string))) 97 | { 98 | throw new Exception("Data payload must contain a \"uid\" key that must not be a string."); 99 | } 100 | else if (containsUid && data["uid"].ToString().Length > 256) 101 | { 102 | throw new Exception("Data payload must contain a \"uid\" key that must not be longer than 256 characters."); 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator.Tests/FirebaseTokenGenerator.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {40A54324-D081-4C1F-8F39-F2DB4BF20166} 7 | Library 8 | Properties 9 | Firebase.Tests 10 | FirebaseTokenGenerator.Tests 11 | v3.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | False 41 | ..\packages\JWT.1.3.1\lib\3.5\JWT.dll 42 | 43 | 44 | 45 | 3.5 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | {edf6d0ec-8015-463c-9b3b-034ef0f897a9} 67 | FirebaseTokenGenerator 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | False 78 | 79 | 80 | False 81 | 82 | 83 | False 84 | 85 | 86 | False 87 | 88 | 89 | 90 | 91 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /FirebaseTokenGenerator.Tests/BasicUnitTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using Firebase; 8 | 9 | namespace Firebase.Tests 10 | { 11 | [TestClass] 12 | public class BasicUnitTest 13 | { 14 | private string FIREBASE_SUPER_SECRET_KEY = "moozooherpderp"; 15 | 16 | [TestMethod] 17 | [ExpectedException(typeof(Exception))] 18 | public void CheckIfBasicLength() 19 | { 20 | var payload = new Dictionary(); 21 | 22 | var tokenGenerator = new TokenGenerator("x"); 23 | var token = tokenGenerator.CreateToken(payload); 24 | } 25 | 26 | [TestMethod] 27 | public void CheckBasicStructureHasCorrectNumberOfFragments() 28 | { 29 | var payload = new Dictionary 30 | { 31 | { "uid", "1" }, 32 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" } 33 | }; 34 | 35 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 36 | var token = tokenGenerator.CreateToken(payload); 37 | 38 | String[] tokenFragments = token.Split('.'); 39 | 40 | Assert.IsTrue(tokenFragments.Length == 3, "Token has the proper number of fragments: jwt metadata, payload, and signature"); 41 | } 42 | 43 | [TestMethod] 44 | public void CheckResultProperlyDoesNotHavePadding() 45 | { 46 | var payload = new Dictionary 47 | { 48 | { "uid", "1" }, 49 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" } 50 | }; 51 | 52 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 53 | var token = tokenGenerator.CreateToken(payload); 54 | 55 | Assert.IsTrue(token.IndexOf('=') < 0); 56 | } 57 | 58 | [TestMethod] 59 | public void CheckIfResultIsUrlSafePlusSign() 60 | { 61 | var payload = new Dictionary 62 | { 63 | { "uid", "1" }, 64 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" } 65 | }; 66 | 67 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 68 | var token = tokenGenerator.CreateToken(payload); 69 | 70 | Assert.IsTrue(token.IndexOf('+') < 0); 71 | } 72 | 73 | [TestMethod] 74 | public void CheckIfResultIsUrlSafePlusSlash() 75 | { 76 | var payload = new Dictionary 77 | { 78 | { "uid", "1" }, 79 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" } 80 | }; 81 | 82 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 83 | var token = tokenGenerator.CreateToken(payload); 84 | 85 | Assert.IsTrue(token.IndexOf('/') < 0); 86 | } 87 | 88 | [TestMethod] 89 | public void CheckIfResultHasWhiteSpace() 90 | { 91 | var payload = new Dictionary 92 | { 93 | { "uid", "1" }, 94 | { "a", "apple" }, 95 | { "b", "banana" }, 96 | { "c", "carrot" }, 97 | { "number", Double.MaxValue }, 98 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" }, 99 | { "herp1", "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.?" } 100 | }; 101 | 102 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 103 | var token = tokenGenerator.CreateToken(payload); 104 | 105 | var pattern = new Regex(@"\s"); 106 | var hasWhiteSpace = pattern.IsMatch(token); 107 | 108 | Assert.IsFalse(hasWhiteSpace, "Token has white space"); 109 | } 110 | 111 | [TestMethod] 112 | public void BasicInspectTest() 113 | { 114 | var customData = "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|"; 115 | var payload = new Dictionary 116 | { 117 | { "uid", "1" }, 118 | { "abc", customData } 119 | }; 120 | 121 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 122 | var tokenOptions = new TokenOptions(DateTime.Now, DateTime.Now, true, true); 123 | 124 | var token = tokenGenerator.CreateToken(payload, tokenOptions); 125 | var decoded = JWT.JsonWebToken.DecodeToObject(token, FIREBASE_SUPER_SECRET_KEY) as Dictionary; 126 | Assert.IsTrue(decoded.ContainsKey("v") && (decoded["v"] is int) && (int.Parse(decoded["v"].ToString()) == 0)); 127 | Assert.IsTrue(decoded.ContainsKey("d") && (decoded["d"] as Dictionary).ContainsKey("abc")); 128 | Assert.IsTrue(decoded.ContainsKey("exp") && (decoded["exp"] is int)); 129 | Assert.IsTrue(decoded.ContainsKey("iat") && (decoded["iat"] is int)); 130 | Assert.IsTrue(decoded.ContainsKey("nbf") && (decoded["nbf"] is int)); 131 | Assert.IsTrue(decoded.ContainsKey("admin") && (decoded["admin"] is bool)); 132 | Assert.IsTrue(decoded.ContainsKey("debug") && (decoded["debug"] is bool)); 133 | } 134 | 135 | [TestMethod] 136 | [ExpectedException(typeof(Exception))] 137 | public void RequireUidInPayload() 138 | { 139 | var payload = new Dictionary 140 | { 141 | { "abc", "0123456789~!@#$%^&*()_+-=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\\<>?\"{}|" } 142 | }; 143 | 144 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 145 | var token = tokenGenerator.CreateToken(payload); 146 | } 147 | 148 | [TestMethod] 149 | [ExpectedException(typeof(Exception))] 150 | public void RequireUidStringInPayload() 151 | { 152 | var payload = new Dictionary 153 | { 154 | { "uid", 1 } 155 | }; 156 | 157 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 158 | var token = tokenGenerator.CreateToken(payload); 159 | } 160 | 161 | [TestMethod] 162 | public void AllowMaxLengthUid() 163 | { 164 | var payload = new Dictionary 165 | { 166 | // 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 256 167 | { "uid", "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456" } 168 | }; 169 | 170 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 171 | var token = tokenGenerator.CreateToken(payload); 172 | } 173 | 174 | [TestMethod] 175 | [ExpectedException(typeof(Exception))] 176 | public void DisallowUidTooLong() 177 | { 178 | var payload = new Dictionary 179 | { 180 | // 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 257 181 | { "uid", "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567" } 182 | }; 183 | 184 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 185 | var token = tokenGenerator.CreateToken(payload); 186 | } 187 | 188 | [TestMethod] 189 | public void AllowEmptyStringUid() 190 | { 191 | var payload = new Dictionary 192 | { 193 | { "uid", "" } 194 | }; 195 | 196 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 197 | var token = tokenGenerator.CreateToken(payload); 198 | } 199 | 200 | [TestMethod] 201 | [ExpectedException(typeof(Exception))] 202 | public void DisallowTokensTooLong() 203 | { 204 | var payload = new Dictionary 205 | { 206 | { "uid", "blah" }, 207 | { "longVar", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345612345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234561234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456" } 208 | }; 209 | 210 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 211 | var token = tokenGenerator.CreateToken(payload); 212 | } 213 | 214 | [TestMethod] 215 | public void AllowNoUidWithAdmin() 216 | { 217 | var tokenOptions = new TokenOptions(null, null, true, false); 218 | 219 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 220 | var token = tokenGenerator.CreateToken(null, tokenOptions); 221 | var payload1 = new Dictionary(); 222 | var token1 = tokenGenerator.CreateToken(payload1, tokenOptions); 223 | var payload2 = new Dictionary 224 | { 225 | { "foo", "bar" } 226 | }; 227 | var token2 = tokenGenerator.CreateToken(payload2, tokenOptions); 228 | } 229 | 230 | [TestMethod] 231 | [ExpectedException(typeof(Exception))] 232 | public void DisallowInvalidUidWithAdmin1() 233 | { 234 | var payload = new Dictionary 235 | { 236 | { "uid", 1 } 237 | }; 238 | 239 | var tokenOptions = new TokenOptions(null, null, true, false); 240 | 241 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 242 | var token = tokenGenerator.CreateToken(payload, tokenOptions); 243 | } 244 | 245 | [TestMethod] 246 | [ExpectedException(typeof(Exception))] 247 | public void DisallowInvalidUidWithAdmin2() 248 | { 249 | var payload = new Dictionary 250 | { 251 | { "uid", null } 252 | }; 253 | 254 | var tokenOptions = new TokenOptions(null, null, true, false); 255 | 256 | var tokenGenerator = new TokenGenerator(FIREBASE_SUPER_SECRET_KEY); 257 | var token = tokenGenerator.CreateToken(payload, tokenOptions); 258 | } 259 | } 260 | } 261 | --------------------------------------------------------------------------------