1package okta 2 3import ( 4 "fmt" 5 "net/url" 6 "time" 7) 8 9// AppsService is a service to retreives applications from OKTA. 10type AppsService service 11 12// AppFilterOptions is used to generate a "Filter" to search for different Apps 13// The values here coorelate to API Search paramgters on the group API 14type AppFilterOptions struct { 15 NextURL *url.URL `url:"-"` 16 GetAllPages bool `url:"-"` 17 NumberOfPages int `url:"-"` 18 Limit int `url:"limit,omitempty"` 19} 20 21// App is the Model for an OKTA Application 22type App struct { 23 ID string `json:"id"` 24 Name string `json:"name"` 25 Label string `json:"label"` 26 Status string `json:"status"` 27 LastUpdated time.Time `json:"lastUpdated"` 28 Created time.Time `json:"created"` 29 Accessibility struct { 30 SelfService bool `json:"selfService"` 31 ErrorRedirectURL interface{} `json:"errorRedirectUrl"` 32 LoginRedirectURL interface{} `json:"loginRedirectUrl"` 33 } `json:"accessibility"` 34 Visibility struct { 35 AutoSubmitToolbar bool `json:"autoSubmitToolbar"` 36 Hide struct { 37 IOS bool `json:"iOS"` 38 Web bool `json:"web"` 39 } `json:"hide"` 40 AppLinks struct { 41 TestorgoneCustomsaml20App1Link bool `json:"testorgone_customsaml20app_1_link"` 42 } `json:"appLinks"` 43 } `json:"visibility"` 44 Features []interface{} `json:"features"` 45 SignOnMode string `json:"signOnMode"` 46 Credentials struct { 47 UserNameTemplate struct { 48 Template string `json:"template"` 49 Type string `json:"type"` 50 } `json:"userNameTemplate"` 51 Signing struct { 52 } `json:"signing"` 53 } `json:"credentials"` 54 Settings struct { 55 App struct { 56 } `json:"app"` 57 Notifications struct { 58 Vpn struct { 59 Network struct { 60 Connection string `json:"connection"` 61 } `json:"network"` 62 Message interface{} `json:"message"` 63 HelpURL interface{} `json:"helpUrl"` 64 } `json:"vpn"` 65 } `json:"notifications"` 66 SignOn struct { 67 DefaultRelayState string `json:"defaultRelayState"` 68 SsoAcsURL string `json:"ssoAcsUrl"` 69 IdpIssuer string `json:"idpIssuer"` 70 Audience string `json:"audience"` 71 Recipient string `json:"recipient"` 72 Destination string `json:"destination"` 73 SubjectNameIDTemplate string `json:"subjectNameIdTemplate"` 74 SubjectNameIDFormat string `json:"subjectNameIdFormat"` 75 ResponseSigned bool `json:"responseSigned"` 76 AssertionSigned bool `json:"assertionSigned"` 77 SignatureAlgorithm string `json:"signatureAlgorithm"` 78 DigestAlgorithm string `json:"digestAlgorithm"` 79 HonorForceAuthn bool `json:"honorForceAuthn"` 80 AuthnContextClassRef string `json:"authnContextClassRef"` 81 SpIssuer interface{} `json:"spIssuer"` 82 RequestCompressed bool `json:"requestCompressed"` 83 AttributeStatements []interface{} `json:"attributeStatements"` 84 } `json:"signOn"` 85 } `json:"settings"` 86 Links struct { 87 Logo []struct { 88 Name string `json:"name"` 89 Href string `json:"href"` 90 Type string `json:"type"` 91 } `json:"logo"` 92 AppLinks []struct { 93 Name string `json:"name"` 94 Href string `json:"href"` 95 Type string `json:"type"` 96 } `json:"appLinks"` 97 Help struct { 98 Href string `json:"href"` 99 Type string `json:"type"` 100 } `json:"help"` 101 Users struct { 102 Href string `json:"href"` 103 } `json:"users"` 104 Deactivate struct { 105 Href string `json:"href"` 106 } `json:"deactivate"` 107 Groups struct { 108 Href string `json:"href"` 109 } `json:"groups"` 110 Metadata struct { 111 Href string `json:"href"` 112 Type string `json:"type"` 113 } `json:"metadata"` 114 } `json:"_links"` 115} 116 117func (a App) String() string { 118 // return Stringify(g) 119 return fmt.Sprintf("App:(ID: {%v} - Name: {%v})\n", a.ID, a.Name) 120} 121 122// GetByID gets a group from OKTA by the Gropu ID. An error is returned if the group is not found 123func (a *AppsService) GetByID(appID string) (*App, *Response, error) { 124 125 u := fmt.Sprintf("apps/%v", appID) 126 req, err := a.client.NewRequest("GET", u, nil) 127 128 if err != nil { 129 return nil, nil, err 130 } 131 132 app := new(App) 133 134 resp, err := a.client.Do(req, app) 135 136 if err != nil { 137 return nil, resp, err 138 } 139 140 return app, resp, err 141} 142 143// AppUser is the model for a user of an OKTA App 144type AppUser struct { 145 ID string `json:"id"` 146 ExternalID string `json:"externalId"` 147 Created time.Time `json:"created"` 148 LastUpdated time.Time `json:"lastUpdated"` 149 Scope string `json:"scope"` 150 Status string `json:"status"` 151 StatusChanged *time.Time `json:"statusChanged"` 152 PasswordChanged *time.Time `json:"passwordChanged"` 153 SyncState string `json:"syncState"` 154 LastSync *time.Time `json:"lastSync"` 155 Credentials struct { 156 UserName string `json:"userName"` 157 Password struct { 158 } `json:"password"` 159 } `json:"credentials"` 160 Profile struct { 161 SecondEmail interface{} `json:"secondEmail"` 162 LastName string `json:"lastName"` 163 MobilePhone interface{} `json:"mobilePhone"` 164 Email string `json:"email"` 165 SalesforceGroups []string `json:"salesforceGroups"` 166 Role string `json:"role"` 167 FirstName string `json:"firstName"` 168 Profile string `json:"profile"` 169 } `json:"profile"` 170 Links struct { 171 App struct { 172 Href string `json:"href"` 173 } `json:"app"` 174 User struct { 175 Href string `json:"href"` 176 } `json:"user"` 177 } `json:"_links"` 178} 179 180// GetUsers returns the members in an App 181// Pass in an optional AppFilterOptions struct to filter the results 182// The Users in the app are returned 183func (a *AppsService) GetUsers(appID string, opt *AppFilterOptions) (appUsers []AppUser, resp *Response, err error) { 184 185 pagesRetreived := 0 186 var u string 187 if opt.NextURL != nil { 188 u = opt.NextURL.String() 189 } else { 190 u = fmt.Sprintf("apps/%v/users", appID) 191 192 if opt.Limit == 0 { 193 opt.Limit = defaultLimit 194 } 195 196 u, _ = addOptions(u, opt) 197 } 198 199 req, err := a.client.NewRequest("GET", u, nil) 200 201 if err != nil { 202 // fmt.Printf("____ERROR HERE\n") 203 return nil, nil, err 204 } 205 resp, err = a.client.Do(req, &appUsers) 206 207 if err != nil { 208 // fmt.Printf("____ERROR HERE 2\n") 209 return nil, resp, err 210 } 211 212 pagesRetreived++ 213 214 if (opt.NumberOfPages > 0 && pagesRetreived < opt.NumberOfPages) || opt.GetAllPages { 215 216 for { 217 218 if pagesRetreived == opt.NumberOfPages { 219 break 220 } 221 if resp.NextURL != nil { 222 223 var userPage []AppUser 224 pageOpts := new(AppFilterOptions) 225 pageOpts.NextURL = resp.NextURL 226 pageOpts.Limit = opt.Limit 227 pageOpts.NumberOfPages = 1 228 229 userPage, resp, err = a.GetUsers(appID, pageOpts) 230 231 if err != nil { 232 return appUsers, resp, err 233 } 234 appUsers = append(appUsers, userPage...) 235 pagesRetreived++ 236 } else { 237 break 238 } 239 240 } 241 } 242 243 return appUsers, resp, err 244} 245 246// AppGroups - Groups assigned to Application 247type AppGroups struct { 248 ID string `json:"id"` 249 LastUpdated time.Time `json:"lastUpdated"` 250 Priority int `json:"priority"` 251 Links struct { 252 User struct { 253 Href string `json:"href"` 254 } `json:"user"` 255 } `json:"_links"` 256} 257 258// GetGroups returns groups assigned to the application - Input appID is the Application GUID 259func (a *AppsService) GetGroups(appID string) (appGroups []AppGroups, resp *Response, err error) { 260 261 var u string 262 u = fmt.Sprintf("apps/%v/groups", appID) 263 264 req, err := a.client.NewRequest("GET", u, nil) 265 266 if err != nil { 267 return nil, nil, err 268 } 269 resp, err = a.client.Do(req, &appGroups) 270 271 if err != nil { 272 return nil, resp, err 273 } 274 275 for { 276 277 if resp.NextURL != nil { 278 279 var appGroupPage []AppGroups 280 281 appGroupPage, resp, err = a.GetGroups(appID) 282 283 if err != nil { 284 return appGroups, resp, err 285 } else { 286 appGroups = append(appGroups, appGroupPage...) 287 288 } 289 } else { 290 break 291 } 292 293 } 294 295 return appGroups, resp, err 296} 297 298// GetUser returns the AppUser model for one app users 299func (a *AppsService) GetUser(appID string, userID string) (appUser AppUser, resp *Response, err error) { 300 301 var u string 302 u = fmt.Sprintf("apps/%v/users/%v", appID, userID) 303 304 req, err := a.client.NewRequest("GET", u, nil) 305 306 if err != nil { 307 return appUser, nil, err 308 } 309 resp, err = a.client.Do(req, &appUser) 310 311 if err != nil { 312 return appUser, resp, err 313 } 314 return appUser, resp, nil 315} 316