• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

okta/H05-Mar-2020-

openapi/H05-Mar-2020-

tests/H05-Mar-2020-

v2/H06-Jun-2020-

vendor/github.com/H05-Mar-2020-

.editorconfigH A D05-Mar-2020284

.gitignoreH A D05-Mar-202014

.travis.ymlH A D05-Mar-202081

CONTRIBUTING.mdH A D05-Mar-20205.8 KiB

Gopkg.lockH A D05-Mar-20201.2 KiB

Gopkg.tomlH A D05-Mar-2020897

LICENSE.mdH A D05-Mar-202010.2 KiB

MakefileH A D05-Mar-20202 KiB

NOTICE.mdH A D05-Mar-2020649

README.mdH A D05-Mar-202015.4 KiB

go.modH A D05-Mar-2020767

go.sumH A D05-Mar-20204.4 KiB

README.md

1[<img src="https://devforum.okta.com/uploads/oktadev/original/1X/bf54a16b5fda189e4ad2706fb57cbb7a1e5b8deb.png" align="right" width="256px"/>](https://devforum.okta.com/)
2[![Build Status](https://img.shields.io/travis/okta/okta-sdk-golang.svg?logo=travis)](https://travis-ci.org/okta/okta-sdk-golang)
3![Beta Release](https://img.shields.io/badge/Beta-Unstable-yellow.svg)
4[![License](https://img.shields.io/github/license/okta/okta-sdk-golang.svg)](https://opensource.org/licenses/Apache-2.0)
5[![Support](https://img.shields.io/badge/support-Developer%20Forum-blue.svg)][devforum]
6[![API Reference](https://img.shields.io/badge/docs-reference-lightgrey.svg)][sdkapiref]
7
8# Okta Golang management SDK
9* [Release status](#release-status)
10* [Need help?](#need-help)
11* [Getting started](#getting-started)
12* [Usage guide](#usage-guide)
13* [Configuration reference](#configuration-reference)
14* [Building the SDK](#building-the-sdk)
15* [Contributing](#contributing)
16
17This repository contains the Okta management SDK for Golang. This SDK can be used in your server-side code to interact with the Okta management API and
18
19* Create and update users with the [Users API](https://developer.okta.com/docs/api/resources/users)
20* Add security factors to users with the [Factors API](https://developer.okta.com/docs/api/resources/factors)
21* Manage groups with the [Groups API](https://developer.okta.com/docs/api/resources/groups)
22* Manage applications with the [Apps API](https://developer.okta.com/docs/api/resources/apps)
23* Much more!
24
25We also publish these libraries for Golang:
26
27* [JWT Verifier](https://github.com/okta/okta-jwt-verifier-golang)
28
29You can learn more on the [Okta + Golang](lang-landing) page in our documentation.
30
31## Release status
32
33This library uses semantic versioning and follows Okta's [library version policy](https://developer.okta.com/code/library-versions/).
34
35| Version | Status                    |
36| ------- | ------------------------- |
37| 0.x     |  ⚠️ Beta Release (Retired)|
38| 1.x     |  ✔️ Release               |
39
40The latest release can always be found on the [releases page][github-releases].
41
42## Need help?
43
44If you run into problems using the SDK, you can
45
46* Ask questions on the [Okta Developer Forums][devforum]
47* Post [issues][github-issues] here on GitHub (for code errors)
48
49## Getting started
50
51To install the Okta Golang SDK in your project, run `go get github.com/okta/okta-sdk-golang/okta`
52
53You'll also need
54
55* An Okta account, called an _organization_ (sign up for a free [developer organization](https://developer.okta.com/signup) if you need one)
56* An [API token](https://developer.okta.com/docs/api/getting_started/getting_a_token)
57
58Construct a client instance by passing it your Okta domain name and API token:
59
60```
61client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
62```
63
64Hard-coding the Okta domain and API token works for quick tests, but for real projects you should use a more secure way of storing these values (such as environment variables). This library supports a few different configuration sources, covered in the [configuration reference](#configuration-reference) section.
65
66### OAuth 2.0
67
68Okta allows you to interact with Okta APIs using scoped OAuth 2.0 access tokens. Each access token enables the bearer to perform specific actions on specific Okta endpoints, with that ability controlled by which scopes the access token contains.
69
70This SDK supports this feature only for service-to-service applications. Check out [our guides](https://developer.okta.com/docs/guides/implement-oauth-for-okta/overview/) to learn more about how to register a new service application using a private and public key pair.
71
72When using this approach you won't need an API Token because the SDK will request an access token for you. In order to use OAuth 2.0, construct a client instance by passing the following parameters:
73
74```
75client, _ := okta.NewClient(context,
76  okta.WithAuthorizationMode("PrivateKey"),
77  okta.WithClientId("{{clientId}}),
78  okta.WithScopes(([]string{"okta.users.manage"})),
79  okta.WithPrivateKey({{PEM PRIVATE KEY BLOCK}})
80)
81```
82
83### Extending the Client
84When calling `okta.NewClient()` we allow for you to pass custom instances of `http.Client` and `cache.Cache`.
85
86```
87myClient := &http.Client{}
88
89myCache := NewCustomCacheDriver()
90
91client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"), okta.WithHttpClient(myClient), okta.WithCacheManager(myCache))
92```
93
94
95### Extending or Creating New Cache Manager
96You can create a custom cache driver by implementing `cache.Cache`
97
98```
99type CustomCacheDriver struct {
100}
101
102func NewCustomCacheDriver() Cache {
103	return CustomCacheDriver{}
104}
105
106func (c CustomCacheDriver) Get(key string) *http.Response {
107	return nil
108}
109
110func (c CustomCacheDriver) Set(key string, value *http.Response) {}
111
112func (c CustomCacheDriver) Delete(key string) {}
113
114func (c CustomCacheDriver) Clear() {}
115
116func (c CustomCacheDriver) Has(key string) bool {
117	return false
118}
119```
120
121## Usage guide
122
123These examples will help you understand how to use this library. You can also browse the full [API reference documentation][sdkapiref].
124
125Once you initialize a `client`, you can call methods to make requests to the Okta API. Most methods are grouped by the API endpoint they belong to. For example, methods that call the [Users API](https://developer.okta.com/docs/api/resources/users) are organized under `client.User`.
126
127### Authenticate a User
128This library should only be used with the Okta management API. To call the [Authentication API](https://developer.okta.com/docs/api/resources/authn), you should construct your own HTTP requests.
129
130### Get a User
131```
132client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
133user, resp, err := client.User.GetUser(user.Id, nil)
134```
135
136### List all Users
137```
138client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
139users, resp, err := client.User.ListUsers()
140```
141
142### Filter or search for Users
143```
144client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
145
146filter := query.NewQueryParams(query.WithFilter("status eq \"ACTIVE\""))
147
148users, resp, err := client.User.ListUsers(filter)
149```
150
151### Create a User
152```
153client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
154
155p := &okta.PasswordCredential{
156		Value: "Abcd1234",
157}
158uc := &okta.UserCredentials{
159		Password: p,
160}
161profile := okta.UserProfile{}
162profile["firstName"] = "John"
163profile["lastName"] = "Activate"
164profile["email"] = "john-activate@example.com"
165profile["login"] = "john-activate@example.com"
166u := &okta.User{
167		Credentials: uc,
168		Profile:     &profile,
169}
170
171user, resp, err := client.User.CreateUser(*u, nil)
172```
173
174### Update a User
175```
176client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
177
178newProfile := *user.Profile
179newProfile["nickName"] = "Batman"
180updatedUser := &okta.User{
181  Profile: &newProfile,
182}
183user, resp, err := client.User.UpdateUser(user.Id, *updatedUser, nil)
184```
185
186### Get and set custom attributes
187Custom attributes must first be defined in the Okta profile editor. Then, you can work with custom attributes on a user:
188```
189client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
190user, resp, err := client.User.GetUser(user.Id, nil)
191
192nickName = user.Profile["nickName"]
193```
194
195### Remove a User
196You must first deactivate the user, and then you can delete the user.
197```
198client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
199resp, err := client.User.DeactivateUser(user.Id, nil)
200
201resp, err := client.User.DeactivateOrDeleteUser(user.Id, nil)
202```
203
204### List a User's Groups
205```
206client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
207
208groups, resp, err := client.User.ListUserGroups(user.Id, nil)
209```
210
211### Create a Group
212```
213client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
214
215gp := &okta.GroupProfile{
216  Name: "Get Test Group",
217}
218g := &okta.Group{
219  Profile: gp,
220}
221group, resp, err := client.Group.CreateGroup(*g, nil)
222```
223
224### Add a User to a Group
225```
226client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
227
228resp, err := client.Group.AddUserToGroup(group.Id, user.Id, nil)
229```
230
231### List a User's enrolled Factors
232```
233client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
234
235allowedFactors, resp, err := client.Factor.ListSupportedFactors(user.Id)
236```
237
238### Enroll a User in a new Factor
239```
240client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
241
242factorProfile := okta.NewSmsFactorProfile()
243factorProfile.PhoneNumber = "5551234567"
244
245factor := okta.NewSmsFactor()
246factor.Profile = factorProfile
247
248addedFactor, resp, err := client.Factor.AddFactor(user.Id, factor, nil)
249```
250
251### Activate a Factor
252```
253client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
254
255factor, resp, err := client.Factor.ActivateFactor(user.Id, factor.Id, nil)
256```
257
258### Verify a Factor
259```
260client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
261
262verifyFactorRequest := okta.VerifyFactorRequest{
263  PassCode: "123456"
264}
265verifyFactorResp, resp, err := client.Factor.VerifyFactor(user.Id, factor.Id, verifyFactorRequest, nil)
266```
267
268### List all Applications
269```
270client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
271
272applications, resp, err := client.Application.ListApplications(nil)
273
274//applications will need to be cast from the interface into its concrete form before you can use it.
275for _, a := range applications {
276		if a.(*okta.Application).Name == "bookmark" {
277			if a.(*okta.Application).Id == app2.(okta.BookmarkApplication).Id {
278				application :=  *a.(*okta.BookmarkApplication) //This will cast it to a Bookmark Application
279			}
280		}
281		// continue for each type you want to work with.
282	}
283```
284
285### Get an Application
286```
287client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
288
289//Getting a Basic Auth Application
290application, resp, err = client.Application.GetApplication(appId, okta.NewBasicAuthApplication(), nil)
291
292//To use the application, you must cast it to the type.
293app := application.(*okta.BasicAuthApplication)
294```
295
296### Create a SWA Application
297```
298client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
299
300swaAppSettingsApp := newSwaApplicationSettingsApplication()
301swaAppSettingsApp.ButtonField = "btn-login"
302swaAppSettingsApp.PasswordField = "txtbox-password"
303swaAppSettingsApp.UsernameField = "txtbox-username"
304swaAppSettingsApp.Url = "https://example.com/login.html"
305swaAppSettingsApp.LoginUrlRegex = "REGEX_EXPRESSION"
306
307swaAppSettings := newSwaApplicationSettings()
308swaAppSettings.App = &swaAppSettingsApp
309
310swaApp := newSwaApplication()
311swaApp.Label = "Test App"
312swaApp.Settings = &swaAppSettings
313
314application, resp, err := client.Application.CreateApplication(swaApp, nil)
315```
316
317### Call other API endpoints
318Not every API endpoint is represented by a method in this library. You can call any Okta management API endpoint using this generic syntax:
319```
320client := okta.NewClient(context, okta.WithOrgUrl("https://{yourOktaDomain}"), okta.WithToken("{apiToken}"))
321
322url := "https://golang.oktapreview.com/api/v1/authorizationServers
323
324type Signing struct {
325	RotationMode string     `json:"rotationMode,omitempty"`
326	LastRotated  *time.Time `json:"lastRotated,omitempty"`
327	NextRotation *time.Time `json:"nextRotation,omitempty"`
328	Kid          string     `json:"kid,omitempty"`
329}
330
331type Credentials struct {
332	Signing *Signing `json:"signing,omitempty"`
333}
334
335type AuthorizationServer struct {
336	Id          string       `json:"id,omitempty"`
337	Name        string       `json:"name,omitempty"`
338	Description string       `json:"description,omitempty"`
339	Audiences   []string     `json:"audiences,omitempty"`
340	Issuer      string       `json:"issuer,omitempty"`
341	IssuerMode  string       `json:"issuerMode,omitempty"`
342	Status      string       `json:"status,omitempty"`
343	Created     *time.Time   `json:"created,omitempty"`
344	LastUpdated *time.Time   `json:"lastUpdated,omitempty"`
345	Credentials *Credentials `json:"credentials,omitempty"`
346	Embedded    interface{}  `json:"_embedded,omitempty"`
347	Links       interface{}  `json:"_links,omitempty"`
348}
349
350as := AuthorizationServer{
351  Name:        "Sample Authorization Server",
352  Description: "Sample Authorization Server description",
353  Audiences:   []string{"api://default"},
354}
355
356req, err := m.client.requestExecutor.NewRequest("POST", url, as)
357if err != nil {
358  return nil, nil, err
359}
360
361var authServer *AuthorizationServer
362resp, err := m.client.requestExecutor.Do(req, &authServer)
363if err != nil {
364  return nil, resp, err
365}
366return authServer, resp, nil
367```
368
369## Configuration reference
370
371This library looks for configuration in the following sources:
372
3730. An `okta.yaml` file in a `.okta` folder in the current user's home directory (`~/.okta/okta.yaml` or `%userprofile\.okta\okta.yaml`)
3740. A `.okta.yaml` file in the application or project's root directory
3750. Environment variables
3760. Configuration explicitly passed to the constructor (see the example in [Getting started](#getting-started))
377
378Higher numbers win. In other words, configuration passed via the constructor will override configuration found in environment variables, which will override configuration in `okta.yaml` (if any), and so on.
379
380### YAML configuration
381
382When you use an API Token instead of OAuth 2.0 the full YAML configuration looks like:
383
384```yaml
385okta:
386  client:
387    connectionTimeout: 30 # seconds
388    orgUrl: "https://{yourOktaDomain}"
389    proxy:
390      port: null
391      host: null
392      username: null
393      password: null
394    token: {apiToken}
395```
396
397When you use OAuth 2.0 the full YAML configuration looks like:
398
399```yaml
400okta:
401  client:
402    connectionTimeout: 30 # seconds
403    orgUrl: "https://{yourOktaDomain}"
404    proxy:
405      port: null
406      host: null
407      username: null
408      password: null
409    authorizationMode: "PrivateKey"
410    clientId: "{yourClientId}"
411    scopes:
412      - scope.1
413      - scope.2
414    privateKey: |
415        -----BEGIN RSA PRIVATE KEY-----
416        MIIEogIBAAKCAQEAl4F5CrP6Wu2kKwH1Z+CNBdo0iteHhVRIXeHdeoqIB1iXvuv4
417        THQdM5PIlot6XmeV1KUKuzw2ewDeb5zcasA4QHPcSVh2+KzbttPQ+RUXCUAr5t+r
418        0r6gBc5Dy1IPjCFsqsPJXFwqe3RzUb...
419        -----END RSA PRIVATE KEY-----
420    requestTimeout: 0 # seconds
421    rateLimit:
422      maxRetries: 4
423```
424
425### Environment variables
426
427Each one of the configuration values above can be turned into an environment variable name with the `_` (underscore) character:
428
429* `OKTA_CLIENT_CONNECTIONTIMEOUT`
430* `OKTA_CLIENT_TOKEN`
431* and so on
432
433## Building the SDK
434
435In most cases, you won't need to build the SDK from source. If you want to build it yourself, you'll need these prerequisites:
436
437- Clone the repo
438- Run `make build` from the root of the project
439
440## Contributing
441
442We're happy to accept contributions and PRs! Please see the [contribution guide](contributing.md) to understand how to structure a contribution.
443
444
445[devforum]: https://devforum.okta.com/
446[sdkapiref]: https://godoc.org/github.com/okta/okta-sdk-golang/okta
447[lang-landing]: https://developer.okta.com/code/golang/
448[github-issues]: /issues
449[github-releases]: /releases
450