Skip to content

Commit 7d1d1ba

Browse files
committed
Update auth to remove secret key and add OpenAI-Organization
1 parent e07bfe2 commit 7d1d1ba

File tree

6 files changed

+80
-36
lines changed

6 files changed

+80
-36
lines changed

OpenAI_API/APIAuthentication.cs

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ public class APIAuthentication
1717
/// The API key, required to access the API endpoint.
1818
/// </summary>
1919
public string ApiKey { get; set; }
20+
/// <summary>
21+
/// The Organization ID to count API requests against. This can be found at https://beta.openai.com/account/org-settings.
22+
/// </summary>
23+
public string OpenAIOrganization { get; set; }
2024

2125
/// <summary>
2226
/// Allows implicit casting from a string, so that a simple string API key can be provided in place of an instance of <see cref="APIAuthentication"/>
@@ -36,7 +40,19 @@ public APIAuthentication(string apiKey)
3640
this.ApiKey = apiKey;
3741
}
3842

39-
private static APIAuthentication cachedDefault = null;
43+
44+
/// <summary>
45+
/// Instantiates a new Authentication object with the given <paramref name="apiKey"/>, which may be <see langword="null"/>. For users who belong to multiple organizations, you can specify which organization is used. Usage from these API requests will count against the specified organization's subscription quota.
46+
/// </summary>
47+
/// <param name="apiKey">The API key, required to access the API endpoint.</param>
48+
/// <param name="openAIOrganization">The Organization ID to count API requests against. This can be found at https://beta.openai.com/account/org-settings.</param>
49+
public APIAuthentication(string apiKey, string openAIOrganization)
50+
{
51+
this.ApiKey = apiKey;
52+
this.OpenAIOrganization = openAIOrganization;
53+
}
54+
55+
private static APIAuthentication cachedDefault = null;
4056

4157
/// <summary>
4258
/// The default authentication to use when no other auth is specified. This can be set manually, or automatically loaded via environment variables or a config file. <seealso cref="LoadFromEnv"/><seealso cref="LoadFromPath(string, string, bool)"/>
@@ -63,21 +79,25 @@ public static APIAuthentication Default
6379
}
6480
}
6581

66-
/// <summary>
67-
/// Attempts to load api keys from environment variables, as "OPENAI_KEY" (or "OPENAI_SECRET_KEY", for backwards compatibility)
68-
/// </summary>
69-
/// <returns>Returns the loaded <see cref="APIAuthentication"/> any api keys were found, or <see langword="null"/> if there were no matching environment vars.</returns>
70-
public static APIAuthentication LoadFromEnv()
82+
/// <summary>
83+
/// Attempts to load api key from environment variables, as "OPENAI_KEY" or "OPENAI_API_KEY". Also loads org if from "OPENAI_ORGANIZATION" if present.
84+
/// </summary>
85+
/// <returns>Returns the loaded <see cref="APIAuthentication"/> any api keys were found, or <see langword="null"/> if there were no matching environment vars.</returns>
86+
public static APIAuthentication LoadFromEnv()
7187
{
72-
var key = Environment.GetEnvironmentVariable("OPENAI_KEY");
73-
74-
if (string.IsNullOrEmpty(key))
75-
key = Environment.GetEnvironmentVariable("OPENAI_SECRET_KEY");
76-
88+
string key = Environment.GetEnvironmentVariable("OPENAI_KEY");
89+
7790
if (string.IsNullOrEmpty(key))
78-
return null;
91+
{
92+
key = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
7993

80-
return new APIAuthentication(key);
94+
if (string.IsNullOrEmpty(key))
95+
return null;
96+
}
97+
98+
string org = Environment.GetEnvironmentVariable("OPENAI_ORGANIZATION");
99+
100+
return new APIAuthentication(key, org);
81101
}
82102

83103
/// <summary>
@@ -93,6 +113,7 @@ public static APIAuthentication LoadFromPath(string directory = null, string fil
93113
directory = Environment.CurrentDirectory;
94114

95115
string key = null;
116+
string org = null;
96117
var curDirectory = new DirectoryInfo(directory);
97118

98119
while (key == null && curDirectory.Parent != null)
@@ -107,13 +128,16 @@ public static APIAuthentication LoadFromPath(string directory = null, string fil
107128
{
108129
switch (parts[0].ToUpper())
109130
{
110-
case "OPENAI_KEY":
111-
key = parts[1].Trim();
112-
break;
113-
case "OPENAI_SECRET_KEY":
114-
key = parts[1].Trim();
115-
break;
116-
default:
131+
case "OPENAI_KEY":
132+
key = parts[1].Trim();
133+
break;
134+
case "OPENAI_API_KEY":
135+
key = parts[1].Trim();
136+
break;
137+
case "OPENAI_ORGANIZATION":
138+
org = parts[1].Trim();
139+
break;
140+
default:
117141
break;
118142
}
119143
}
@@ -133,7 +157,7 @@ public static APIAuthentication LoadFromPath(string directory = null, string fil
133157
if (string.IsNullOrEmpty(key))
134158
return null;
135159

136-
return new APIAuthentication(key);
160+
return new APIAuthentication(key, org);
137161
}
138162

139163

OpenAI_API/Completions/CompletionEndpoint.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public async Task<CompletionResult> CreateCompletionAsync(CompletionRequest requ
4949
HttpClient client = new HttpClient();
5050
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Api.Auth.ApiKey);
5151
client.DefaultRequestHeaders.Add("User-Agent", "okgodoit/dotnet_openai_api");
52+
if (!string.IsNullOrEmpty(Api.Auth.OpenAIOrganization)) client.DefaultRequestHeaders.Add("OpenAI-Organization", Api.Auth.OpenAIOrganization);
5253

5354
string jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
5455
var stringContent = new StringContent(jsonContent, UnicodeEncoding.UTF8, "application/json");

OpenAI_API/Engine/EnginesEndpoint.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public static async Task<List<Engine>> GetEnginesAsync(APIAuthentication auth =
5555
HttpClient client = new HttpClient();
5656
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", auth.ThisOrDefault().ApiKey);
5757
client.DefaultRequestHeaders.Add("User-Agent", "okgodoit/dotnet_openai_api");
58+
if (!string.IsNullOrEmpty(auth.ThisOrDefault().OpenAIOrganization)) client.DefaultRequestHeaders.Add("OpenAI-Organization", auth.ThisOrDefault().OpenAIOrganization);
5859

5960
var response = await client.GetAsync(@"https://api.openai.com/v1/engines");
6061
string resultAsString = await response.Content.ReadAsStringAsync();

OpenAI_API/Search/SearchEndpoint.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public async Task<Dictionary<string, double>> GetSearchResultsAsync(SearchReques
4343
HttpClient client = new HttpClient();
4444
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", Api.Auth.ApiKey);
4545
client.DefaultRequestHeaders.Add("User-Agent", "okgodoit/dotnet_openai_api");
46+
if (!string.IsNullOrEmpty(Api.Auth.OpenAIOrganization)) client.DefaultRequestHeaders.Add("OpenAI-Organization", Api.Auth.OpenAIOrganization);
4647

4748
string jsonContent = JsonConvert.SerializeObject(request, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore });
4849
var stringContent = new StringContent(jsonContent, UnicodeEncoding.UTF8, "application/json");

OpenAI_Tests/AuthTests.cs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ public class AuthTests
99
[SetUp]
1010
public void Setup()
1111
{
12-
File.WriteAllText(".openai", "OPENAI_KEY=pk-test12");
13-
Environment.SetEnvironmentVariable("OPENAI_KEY", "pk-test-env");
14-
//Environment.SetEnvironmentVariable("OPENAI_SECRET_KEY", "sk-test-env");
15-
}
12+
File.WriteAllText(".openai", "OPENAI_KEY=pk-test12"+Environment.NewLine+ "OPENAI_ORGANIZATION=org-testing123");
13+
Environment.SetEnvironmentVariable("OPENAI_API_KEY", "pk-test-env");
14+
Environment.SetEnvironmentVariable("OPENAI_ORGANIZATION", "org-testing123");
15+
}
1616

17-
[Test]
17+
[Test]
1818
public void GetAuthFromEnv()
1919
{
2020
var auth = OpenAI_API.APIAuthentication.LoadFromEnv();
@@ -47,14 +47,20 @@ public void GetDefault()
4747
{
4848
var auth = OpenAI_API.APIAuthentication.Default;
4949
var envAuth = OpenAI_API.APIAuthentication.LoadFromEnv();
50-
Assert.IsNotNull(auth);
51-
Assert.IsNotNull(auth.ApiKey);
52-
Assert.AreEqual(envAuth.ApiKey, auth.ApiKey);
53-
}
50+
Assert.IsNotNull(auth);
51+
Assert.IsNotNull(auth.ApiKey);
52+
Assert.IsNotNull(envAuth);
53+
Assert.IsNotNull(envAuth.ApiKey);
54+
Assert.AreEqual(envAuth.ApiKey, auth.ApiKey);
55+
Assert.IsNotNull(auth.OpenAIOrganization);
56+
Assert.IsNotNull(envAuth.OpenAIOrganization);
57+
Assert.AreEqual(envAuth.OpenAIOrganization, auth.OpenAIOrganization);
5458

59+
}
5560

5661

57-
[Test]
62+
63+
[Test]
5864
public void testHelper()
5965
{
6066
OpenAI_API.APIAuthentication defaultAuth = OpenAI_API.APIAuthentication.Default;
@@ -87,13 +93,16 @@ public void ParseKey()
8793
var auth = new OpenAI_API.APIAuthentication("pk-testAA");
8894
Assert.IsNotNull(auth.ApiKey);
8995
Assert.AreEqual("pk-testAA", auth.ApiKey);
96+
Assert.IsNull(auth.OpenAIOrganization);
9097
auth = "pk-testCC";
9198
Assert.IsNotNull(auth.ApiKey);
9299
Assert.AreEqual("pk-testCC", auth.ApiKey);
93100

94-
auth = new OpenAI_API.APIAuthentication("sk-testBB");
101+
auth = new OpenAI_API.APIAuthentication("sk-testBB", "orgTest");
95102
Assert.IsNotNull(auth.ApiKey);
96103
Assert.AreEqual("sk-testBB", auth.ApiKey);
104+
Assert.IsNotNull(auth.OpenAIOrganization);
105+
Assert.AreEqual("orgTest", auth.OpenAIOrganization);
97106
}
98107

99108
}

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@ Install-Package OpenAI
3636
### Authentication
3737
There are 3 ways to provide your API keys, in order of precedence:
3838
1. Pass keys directly to `APIAuthentication(string key)` constructor
39-
2. Set environment var for OPENAI_KEY
39+
2. Set environment var for OPENAI_API_KEY (or OPENAI_KEY for backwards compatability)
4040
3. Include a config file in the local directory or in your user directory named `.openai` and containing the line:
4141
```shell
42-
OPENAI_KEY=sk-aaaabbbbbccccddddd
42+
OPENAI_API_KEY=sk-aaaabbbbbccccddddd
4343
```
4444

4545
You use the `APIAuthentication` when you initialize the API as shown:
4646
```csharp
4747
// for example
48-
OpenAIAPI api = new OpenAIAPI("sk-mykeyhere"); // shorthand
48+
OpenAIAPI api = new OpenAIAPI("YOUR_API_KEY"); // shorthand
4949
// or
50-
OpenAIAPI api = new OpenAIAPI(new APIAuthentication("sk-secretkey")); // create object manually
50+
OpenAIAPI api = new OpenAIAPI(new APIAuthentication("YOUR_API_KEY")); // create object manually
5151
// or
5252
OpenAIAPI api = new OpenAIAPI(APIAuthentication LoadFromEnv()); // use env vars
5353
// or
@@ -56,6 +56,14 @@ OpenAIAPI api = new OpenAIAPI(APIAuthentication LoadFromPath()); // use config f
5656
OpenAIAPI api = new OpenAIAPI(); // uses default, env, or config file
5757
```
5858

59+
You may optionally include an openAIOrganization (OPENAI_ORGANIZATION in env or config file) specifying which organization is used for an API request. Usage from these API requests will count against the specified organization's subscription quota. Organization IDs can be found on your [Organization settings](https://beta.openai.com/account/org-settings) page.
60+
```csharp
61+
// for example
62+
OpenAIAPI api = new OpenAIAPI(new APIAuthentication("YOUR_API_KEY","org-yourOrgHere"));
63+
```
64+
65+
66+
5967
### Completions
6068
The Completion API is accessed via `OpenAIAPI.Completions`:
6169

0 commit comments

Comments
 (0)